webmcp-platform
v1.0.0
Published
Unified WebMCP platform — tool registration, discovery, x402 payments, and polyfill in one package
Maintainers
Readme
webmcp-platform
The full-stack WebMCP toolkit. Register tools, accept payments, and let AI agents discover everything — in one package.
npm install webmcp-platformWhat this does
webmcp-platform unifies three concerns that every agent-ready website needs:
- Tool Registration — Define what your site can do (free and paid)
- Payment Acceptance — x402 on-chain payments via Base/USDC — zero custodial infra
- Agent Discovery —
/.well-known/webmcpmanifest so agents find your tools and know what they cost
Under the hood it wires together webmcp-polyfill (navigator.modelContext) and webmcp-payments (x402 payment gate) into a single createPlatform() call.
5-Minute Setup
import express from 'express';
import { createPlatform } from 'webmcp-platform';
const app = express();
app.use(express.json());
// 1. Create the platform
const platform = createPlatform({
polyfill: true, // installs navigator.modelContext
payments: {
merchantWallet: '0x742d35Cc6634C0532925a3b844Bc9e7595f2bD18',
chain: 'base',
acceptedTokens: ['USDC'],
feeRate: 0.01, // 1% platform fee
},
});
// 2. Register a free tool
platform.tool('search', {
description: 'Search products by keyword',
input: {
type: 'object',
properties: { query: { type: 'string' } },
required: ['query'],
},
execute: async ({ query }) => {
const results = await searchProducts(query as string);
return { results };
},
});
// 3. Register a paid tool — agents pay 50¢ USDC per call
platform.paidTool('premium-report', {
description: 'Full market analysis with charts and projections',
price: '0.50',
token: 'USDC',
input: {
type: 'object',
properties: { symbol: { type: 'string' } },
required: ['symbol'],
},
execute: async ({ symbol }) => {
const report = await generateReport(symbol as string);
return { report };
},
});
// 4. Mount middleware — handles discovery + x402 + tool execution
app.use(platform.middleware());
app.listen(3000, () => console.log('Agent-ready at http://localhost:3000'));That's it. Agents can now:
GET /.well-known/webmcp→ discover all tools + pricingPOST /webmcp/tools/search→ execute free tools directlyPOST /webmcp/tools/premium-report→ get a 402 with payment envelope → pay → execute
API
createPlatform(config?)
Creates the unified platform instance.
const platform = createPlatform({
polyfill: true, // default: true — auto-install navigator.modelContext
forcePolyfill: false, // default: false — skip native Chrome 146+ detection
baseUrl: 'https://api.example.com',
payments: {
merchantWallet: '0x...',
chain: 'base', // 'base' | 'base-sepolia' | 'arbitrum' | 'optimism'
acceptedTokens: ['USDC'],
feeRate: 0.01,
paymentTtl: 300, // payment envelope TTL in seconds
rpcUrl: 'https://...', // custom RPC
},
});platform.tool(name, options)
Register a free tool.
platform.tool('lookup', {
description: 'Look up an entity by ID',
input: { type: 'object', properties: { id: { type: 'string' } } },
execute: async ({ id }) => getEntity(id),
});platform.paidTool(name, options)
Register a paid tool. Requires payments config.
platform.paidTool('analyze', {
description: 'Deep analysis',
price: '1.00',
token: 'USDC', // optional, defaults to first acceptedToken
chain: 'base', // optional, defaults to platform chain
input: { type: 'object', properties: { data: { type: 'string' } } },
execute: async ({ data }) => runAnalysis(data),
});platform.middleware()
Express middleware that handles:
GET /.well-known/webmcp→ serves discovery manifestPOST /webmcp/tools/:name→ executes tools (with x402 for paid tools)- Everything else →
next()
platform.discoveryHandler()
Standalone handler for the discovery endpoint. Use when you want manual control:
app.get('/.well-known/webmcp', platform.discoveryHandler());platform.expressRouter()
Full Express router including discovery, tool listing, and execution:
app.use(platform.expressRouter());
// Adds: GET /.well-known/webmcp, GET /webmcp/tools, POST /webmcp/tools/:nameplatform.manifest()
Generate the discovery manifest programmatically:
const manifest = platform.manifest();
// { version: '1', tools: [...], paymentConfig: { ... } }Properties
| Property | Type | Description |
|----------|------|-------------|
| platform.tools | RegisteredTool[] | All registered tools |
| platform.registry | ToolRegistry | Internal registry (advanced use) |
| platform.modelContext | ModelContextAPI \| null | Polyfill instance |
| platform.paymentGate | PaymentGate \| null | Payment gate instance |
| platform.config | PlatformConfig | Platform configuration |
How x402 Payment Flow Works
Agent Your Server
│ │
├─ GET /.well-known/webmcp ────→│ ← discover tools + pricing
│←── { tools: [...], pricing }──│
│ │
├─ POST /webmcp/tools/report ──→│ ← no payment header
│←── 402 { paymentRequired: { │
│ protocol: 'x402', │
│ chain: 'base', │
│ token: 'USDC', │
│ amount: '500000', │
│ recipient: '0x...', │
│ nonce: 'abc123', │
│ expiresAt: 1709... │
│ }} │
│ │
├─ [pays on-chain via USDC] ───→ Base L2
│ │
├─ POST /webmcp/tools/report │ ← with payment headers
│ X-Payment-Tx: 0xabc... │
│ X-Payment-Chain: base │
│ X-Payment-Nonce: abc123 │
│ X-Payment-Payer: 0x... │
│←── 200 { result: ... } ─────│ ← verified + executedMigration from @mcp-b/global
Currently using the @mcp-b/global polyfill? Swap one import:
- import '@mcp-b/global';
+ import { createPlatform } from 'webmcp-platform';
+ const platform = createPlatform({ polyfill: true });Your existing navigator.modelContext.registerTool() calls keep working. But now you also get:
- Payments — monetize any tool with one line
- Discovery — agents find your tools at
/.well-known/webmcp - Express integration — middleware handles the full flow
- SSR support — works in Node.js without JSDOM hacks
- Smaller bundle — 2.94KB polyfill vs 4.2KB @mcp-b/global
- TypeScript strict — no
anyleaks
Comparison
| Feature | webmcp-platform | @mcp-b/global + DIY |
|---------|----------------|---------------------|
| navigator.modelContext polyfill | ✅ Built-in | ✅ Separate package |
| Tool registration | ✅ platform.tool() | ✅ registerTool() |
| Payment gating (x402) | ✅ platform.paidTool() | ❌ Build your own |
| Discovery manifest | ✅ /.well-known/webmcp | ❌ Build your own |
| Express middleware | ✅ platform.middleware() | ❌ Build your own |
| On-chain verification | ✅ PaymentVerifier | ❌ Build your own |
| SSR / Node.js | ✅ First-class | ⚠️ Needs workarounds |
| TypeScript strict | ✅ Zero any | ⚠️ Loose types |
| Bundle size (polyfill) | 2.94KB | 4.2KB |
| Setup time | 5 minutes | Hours to weeks |
Free-Only Mode
Don't need payments? Skip the config:
const platform = createPlatform({ polyfill: true });
platform.tool('search', {
description: 'Free search',
input: { type: 'object', properties: { q: { type: 'string' } } },
execute: async ({ q }) => search(q),
});
app.use(platform.middleware());Advanced: Direct Sub-Package Access
Need lower-level control? Everything is re-exported:
import {
// Polyfill
installPolyfill,
createModelContext,
ModelContext,
// Payments
PaymentGate,
PaymentVerifier,
PaymentDiscovery,
// Registry
ToolRegistry,
// Middleware
createMiddleware,
createDiscoveryHandler,
} from 'webmcp-platform';Requirements
- Node.js >= 18
- Express >= 4 (optional peer dependency)
- For on-chain verification: RPC access to Base (default public RPC included)
License
MIT
