mcp-tools
mcp-tools
Cloudflare Workers that speak MCP, in one TypeScript repo.
core/mcp.ts shared plumbing: HTTP MCP endpoint + RPC surface + tool typing
workers/mcp-wp/ WordPress REST API -> MCP
workers/mcp-toolkit/ aggregator: its own tools + every worker bound under `services`
scripts/mock-wp.mjs fake WordPress for local testingA worker is a tools object
import cfg from "../wrangler.json";
import pkg from "../package.json";
import { mcpWorker, tool } from "../../../core/mcp";
export default mcpWorker({
...cfg, // name + services come straight from wrangler.json
version: pkg.version,
tools: {
hello: tool({
description: "Say hi",
input: { type: "object", required: ["name"], properties: { name: { type: "string" } } },
run: ({ name }) => `Hi ${name}`, // `name` is typed from `input`; nothing declared twice
}),
},
});Rules the core enforces so nothing needs a mapping table:
The object key is the tool name. Exposed as
<worker>_<key>: workermcp-wp->wp_search_posts.runmay return a string, any JSON value, or a full MCP result ({ content, isError }).toolsmay be a function of the request context when tools depend on the connector URL.A worker with
servicesin its wrangler.json re-exports those workers' tools and routes calls by prefix. The connector's query string is forwarded, so each worker reads its own params.
Connector URLs
URL | You get |
| everything |
| only the |
| exactly those two |
| tools generated from that site (posts, events, …) |
| one set per site, named |
| the wp worker alone ( |
Local development
npm install
npm run check # wrangler types + tsc, every worker
npm run format # prettier, 100 columns
node scripts/mock-wp.mjs 8799 & # a fake WordPress
cd workers/mcp-toolkit && npx wrangler dev -c wrangler.json -c ../mcp-wp/wrangler.json
curl 'http://localhost:8787/?wp=http://localhost:8799' # lists the generated toolsworker-configuration.d.ts is generated by wrangler types and committed so any editor
type-checks a fresh clone. Re-run npm run check after touching a wrangler.json.
Deploying (Workers Builds, per worker)
Dashboard -> the Worker -> Settings -> Build -> Connect repository:
Setting | Value |
Root directory |
|
Build command |
|
Deploy command |
|
Build watch paths |
|
The Worker name in the dashboard must equal name in that folder's wrangler.json.
Bindings live in wrangler.json; secrets stay in the dashboard (keep_vars keeps plain vars too).
Adding a worker
Copy
workers/mcp-wptoworkers/mcp-<name>; setnameinwrangler.jsonandpackage.json.Replace
toolsinsrc/index.ts.Add
{ "binding": "<NAME>", "service": "mcp-<name>" }toworkers/mcp-toolkit/wrangler.json.npm run check, commit, connect the new Worker to the repo as above.
Auth (Cloudflare Access)
Access runs before the Worker, so unauthenticated hits cost nothing. Per worker:
Zero Trust -> Integrations -> Identity providers -> add One-time PIN (email code, no account needed).
Workers & Pages -> the Worker -> Access -> protect it; policy: Include -> Emails -> your list.
Zero Trust -> Access controls -> Applications -> edit that application -> Advanced settings -> turn on Managed OAuth, allow dynamic client registration.
In Claude.ai, add the connector URL. The browser login is the Access page.
Adding a person = adding their email to the policy.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/stef7/mcp-tools'
If you have feedback or need assistance with the MCP directory API, please join our Discord server