agenticschema
Turns the Schema.org markup already present in a webpage into MCP tools an AI agent can call, extracting JSON-LD, microdata, and RDFa to expose read-only and custom tools. It runs as a stdio or Streamable HTTP MCP server, enabling agents to interact with page entities without additional APIs or backends.
README
AgenticSchema ·

Turn the Schema.org markup a page already has into MCP tools an AI agent can call.
Most pages already publish structured data. Agents still scrape them. This library closes that
gap: it reads the JSON-LD, microdata and RDFa already in the page and emits Model Context
Protocol tools — no new API to write, no backend to run.
┌──────────────── @agenticschema/core ─────────────────┐
Document │ HTML │ │
│ JSON-LD ───────► │ extract ──► normalize ──► select ──► map ──► guard │ ──► ToolDescriptor[]
└──────────────────────────────────────────────────────┘
│
┌───────────────────┴───────────────────┐
▼ ▼
@agenticschema/browser @agenticschema/server
document.modelContext stdio / Streamable HTTP
(script tag, WebMCP) (works with any MCP client today)
Try it
Three ways in, in rising order of commitment.
1. In the browser, nothing installed
Paste any JSON-LD and watch the tools appear. Try the hostile sample: it is the fastest way to see what the library refuses and why. Alongside it, a live page carrying the script tag for the WebMCP path end to end.
Both pages load the packages from jsDelivr at exact versions, so what you are trying is what you would ship, not a local build.
2. Read a real page from the terminal
npx @agenticschema/server https://en.wikipedia.org/wiki/Backpack
Wire it into Claude Desktop:
{
"mcpServers": {
"page": {
"command": "npx",
"args": ["-y", "@agenticschema/server", "https://en.wikipedia.org/wiki/Backpack"]
}
}
}
Every entity also becomes a readable MCP resource, which the browser adapter cannot do.
3. On your own site
<script type="module" src="https://cdn.jsdelivr.net/npm/@agenticschema/browser@0.1"></script>
The page registers its tools through WebMCP
(document.modelContext). SPA route changes are picked up automatically.
Three things to know before pasting that in:
- Pin the version. The unpinned specifier always serves the latest release, and jsDelivr caches unversioned URLs at the edge for days — long enough to keep handing out a build you have already replaced. Note that 0.1.1 and earlier register no tools at all on a browser without native WebMCP: the polyfill was left out of the bundle.
- Content-Security-Policy. A page with a CSP has to allow
cdn.jsdelivr.netinscript-src, or the tag never executes. Self-hostdist/cdn/auto.jsif you would rather not open the CDN — it is a single self-contained file. - Registered is not the same as reachable. The tag publishes the tools to the page. An agent still has to be attached to the tab to call them, through a WebMCP-capable browser or an extension. With nothing attached the tools are there and no one is asking.
What it produces on real pages
Two pages, both openly licensed, run through the pipeline exactly as they are published today:
en.wikipedia.org/wiki/Backpack
read get_article
read get_article_author
read get_article_publisher
read get_media
world.openfoodfacts.org/product/3017620422003
read get_web_site
read get_organization
read get_search_action
action search_web_site(search_term_string)
The second one is the interesting case. search_web_site is executable: an agent holding
it queries Open Food Facts directly, instead of guessing a URL or going through a search
engine. It exists because that page publishes a SearchAction whose target sits on its own
origin, which is the only shape that gets past the guard described below.
get_search_action in that list is noise — a reader over the action's own definition, which
is of no use to an agent. It is a known rough edge, left visible here rather than trimmed out
of the example.
Sites were picked for their licensing, not their fame. Wikipedia and Open Food Facts both publish under open licences and permit automated access; plenty of better-known sites forbid it in their terms, and pointing this tool at them is on you.
Three constraints that shaped the design
A page cannot expose an MCP endpoint. Not "it's hard" — a browser tab cannot listen on a
port. In the browser the transport is document.modelContext, provided by the browser itself.
This library is the mapping layer, not a transport.
WebMCP exposes tools only. No resources, no prompts — the W3C explainer is explicit. So entities become read tools in the browser. The Node adapter, which speaks full MCP, exposes them as resources as well.
potentialAction is rare in the wild. In practice it is almost only SearchAction, and
Google retired the Sitelinks Searchbox in November 2024, so adoption is falling. Auto-derivation
alone would produce a read-only library. That is why defineTool() is a first-class feature,
not an afterthought.
Actions are deliberately restricted
Read tools are always generated. Executable tools are not:
| Condition | Result |
|---|---|
SearchAction, FindAction, ReadAction, ViewAction |
eligible |
httpMethod absent or GET |
eligible |
| Destination same-origin (or explicitly allow-listed) | eligible |
Anything else — OrderAction, POST, cross-origin, non-http scheme |
skipped, with a diagnostic |
A site adding one script tag must not become orderable by any passing agent. Anything with side effects goes through explicit opt-in:
import { start } from '@agenticschema/browser';
start({
custom: [{
name: 'check_stock',
description: 'Check in-store availability for a postal code',
inputSchema: {
type: 'object',
properties: { postalCode: { type: 'string' } },
required: ['postalCode'],
additionalProperties: false,
},
execute: async ({ postalCode }) => ({
content: [{ type: 'text', text: await (await fetch(`/api/stock?cap=${postalCode}`)).text() }],
}),
}],
});
Security
The library takes page content and puts it into a model's context. Two attack channels are
closed in core, so every adapter inherits them:
- Prompt injection. A
ld+jsonblock injected through UGC or a compromised CMS can carry instructions. Page text never enters a tool's description — only its data — and is stripped of HTML and control characters, with length caps. - Exfiltration via
urlTemplate. A hostile action could point elsewhere and receive the parameters. Destinations are same-origin by default, https-only, RFC 6570 level 1 only, and re-validated after template expansion so a crafted value cannot move the target.
Plus a cap on tool count (default 24) and on payload size, because agents degrade badly with
large or bloated toolsets. Secondary entities of the same type collapse into a single tool —
nine indistinguishable get_person tools are useless to an agent; one list_person is not.
Packages
| Package | Purpose |
|---|---|
@agenticschema/core |
The pipeline. No MCP, no DOM assumptions. Zero runtime dependencies. |
@agenticschema/profiles |
~20 hand-written type profiles + the Schema.org hierarchy. |
@agenticschema/browser |
WebMCP adapter. Script-tag build is one self-contained file, 27 KB gzip, polyfill included. |
@agenticschema/server |
MCP server over stdio or Streamable HTTP. |
How it compares
schema-org-mcpserves the Schema.org vocabulary to an LLM (validate types, generate snippets). It does not look at real pages.wmcp.shis a hosted SaaS doing something adjacent server-side. This is an embeddable open-source library, client-side first.@mcp-b/*provide the WebMCP transport and polyfill. This builds on them; it does not replace them.
The mapping layer — Schema.org to MCP — is the part that did not exist.
Development
npm install
npm test # 100 tests, including a corpus captured from real pages
npm run typecheck
npm run build
npm run size # fails if the script-tag build has an import a browser cannot
# resolve, or goes over 30 KB gzip
npm run corpus:fetch refreshes the real-page fixtures.
npm run build:hierarchy -w @agenticschema/profiles regenerates the Schema.org type hierarchy.
Status and disclaimer
Early, pre-1.0, API not stable. WebMCP itself is a proposal — Chrome 151 ships it only behind
--enable-experimental-web-platform-features, which is why the polyfill is a hard dependency of
the browser adapter rather than an optional one.
Provided as is, with no warranty of any kind, express or implied. Use at your own risk. The author accepts no liability for any damage, data loss, security incident, or other consequence arising from use of this software — see the MIT licence for the binding terms. If you put this in front of an agent that can act on someone's behalf, read SECURITY.md first: it sets out what the threat model does and, more importantly, does not cover.
MIT.
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。