mcp-trellis 1.0.0 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +65 -93
- package/dist/adapters/node-request.d.ts +53 -0
- package/dist/adapters/node-request.d.ts.map +1 -0
- package/dist/adapters/node-request.js +165 -0
- package/dist/adapters/node-request.js.map +1 -0
- package/dist/adapters/node.d.ts +13 -30
- package/dist/adapters/node.d.ts.map +1 -1
- package/dist/adapters/node.js +55 -101
- package/dist/adapters/node.js.map +1 -1
- package/dist/advanced.d.ts +18 -0
- package/dist/advanced.d.ts.map +1 -0
- package/dist/advanced.js +18 -0
- package/dist/advanced.js.map +1 -0
- package/dist/app-options.d.ts +132 -0
- package/dist/app-options.d.ts.map +1 -0
- package/dist/app-options.js +2 -0
- package/dist/app-options.js.map +1 -0
- package/dist/app.d.ts +2 -89
- package/dist/app.d.ts.map +1 -1
- package/dist/app.js +143 -63
- package/dist/app.js.map +1 -1
- package/dist/audit.d.ts +5 -5
- package/dist/audit.d.ts.map +1 -1
- package/dist/audit.js +19 -8
- package/dist/audit.js.map +1 -1
- package/dist/auth/bearer.d.ts +4 -1
- package/dist/auth/bearer.d.ts.map +1 -1
- package/dist/auth/bearer.js +19 -4
- package/dist/auth/bearer.js.map +1 -1
- package/dist/auth/signed-token.d.ts +26 -0
- package/dist/auth/signed-token.d.ts.map +1 -0
- package/dist/auth/signed-token.js +96 -0
- package/dist/auth/signed-token.js.map +1 -0
- package/dist/clients.js +1 -1
- package/dist/clients.js.map +1 -1
- package/dist/deprecated.d.ts +42 -0
- package/dist/deprecated.d.ts.map +1 -0
- package/dist/deprecated.js +35 -0
- package/dist/deprecated.js.map +1 -0
- package/dist/{body.d.ts → http/body.d.ts} +27 -6
- package/dist/http/body.d.ts.map +1 -0
- package/dist/{body.js → http/body.js} +33 -13
- package/dist/http/body.js.map +1 -0
- package/dist/http/http.d.ts +42 -0
- package/dist/http/http.d.ts.map +1 -0
- package/dist/http/http.js +100 -0
- package/dist/http/http.js.map +1 -0
- package/dist/http/origins.d.ts +37 -0
- package/dist/http/origins.d.ts.map +1 -0
- package/dist/http/origins.js +87 -0
- package/dist/http/origins.js.map +1 -0
- package/dist/{dispatch.d.ts → mcp/dispatch.d.ts} +1 -1
- package/dist/mcp/dispatch.d.ts.map +1 -0
- package/dist/mcp/dispatch.js +99 -0
- package/dist/mcp/dispatch.js.map +1 -0
- package/dist/{jsonrpc.d.ts → mcp/jsonrpc.d.ts} +9 -0
- package/dist/mcp/jsonrpc.d.ts.map +1 -0
- package/dist/mcp/jsonrpc.js +88 -0
- package/dist/mcp/jsonrpc.js.map +1 -0
- package/dist/{methods.d.ts → mcp/methods.d.ts} +60 -11
- package/dist/mcp/methods.d.ts.map +1 -0
- package/dist/mcp/methods.js +84 -0
- package/dist/mcp/methods.js.map +1 -0
- package/dist/{protocol.d.ts → mcp/protocol.d.ts} +1 -3
- package/dist/mcp/protocol.d.ts.map +1 -0
- package/dist/{protocol.js → mcp/protocol.js} +1 -3
- package/dist/mcp/protocol.js.map +1 -0
- package/dist/mcp/registry.d.ts +58 -0
- package/dist/mcp/registry.d.ts.map +1 -0
- package/dist/mcp/registry.js +81 -0
- package/dist/mcp/registry.js.map +1 -0
- package/dist/mcp/rpc-handlers.d.ts +11 -0
- package/dist/mcp/rpc-handlers.d.ts.map +1 -0
- package/dist/mcp/rpc-handlers.js +133 -0
- package/dist/mcp/rpc-handlers.js.map +1 -0
- package/dist/{tools.d.ts → mcp/tools.d.ts} +20 -1
- package/dist/mcp/tools.d.ts.map +1 -0
- package/dist/mcp/tools.js +166 -0
- package/dist/mcp/tools.js.map +1 -0
- package/dist/{validate.d.ts → mcp/validate.d.ts} +18 -21
- package/dist/mcp/validate.d.ts.map +1 -0
- package/dist/{validate.js → mcp/validate.js} +59 -41
- package/dist/mcp/validate.js.map +1 -0
- package/dist/oauth/audit.d.ts +20 -0
- package/dist/oauth/audit.d.ts.map +1 -0
- package/dist/oauth/audit.js +29 -0
- package/dist/oauth/audit.js.map +1 -0
- package/dist/oauth/cimd/cimd-parse.d.ts +4 -0
- package/dist/oauth/cimd/cimd-parse.d.ts.map +1 -0
- package/dist/oauth/cimd/cimd-parse.js +70 -0
- package/dist/oauth/cimd/cimd-parse.js.map +1 -0
- package/dist/oauth/cimd/cimd-ssrf.d.ts +8 -0
- package/dist/oauth/cimd/cimd-ssrf.d.ts.map +1 -0
- package/dist/oauth/cimd/cimd-ssrf.js +193 -0
- package/dist/oauth/cimd/cimd-ssrf.js.map +1 -0
- package/dist/oauth/cimd/cimd.d.ts +36 -0
- package/dist/oauth/cimd/cimd.d.ts.map +1 -0
- package/dist/oauth/cimd/cimd.js +132 -0
- package/dist/oauth/cimd/cimd.js.map +1 -0
- package/dist/oauth/cimd/types.d.ts +12 -0
- package/dist/oauth/cimd/types.d.ts.map +1 -0
- package/dist/oauth/cimd/types.js +3 -0
- package/dist/oauth/cimd/types.js.map +1 -0
- package/dist/oauth/config.d.ts +51 -0
- package/dist/oauth/config.d.ts.map +1 -0
- package/dist/oauth/config.js +108 -0
- package/dist/oauth/config.js.map +1 -0
- package/dist/oauth/constants.d.ts +11 -0
- package/dist/oauth/constants.d.ts.map +1 -1
- package/dist/oauth/constants.js +11 -0
- package/dist/oauth/constants.js.map +1 -1
- package/dist/oauth/{base64url.d.ts → crypto/base64url.d.ts} +0 -1
- package/dist/oauth/crypto/base64url.d.ts.map +1 -0
- package/dist/oauth/{base64url.js → crypto/base64url.js} +0 -1
- package/dist/oauth/crypto/base64url.js.map +1 -0
- package/dist/oauth/crypto/clientauth.d.ts +13 -0
- package/dist/oauth/crypto/clientauth.d.ts.map +1 -0
- package/dist/oauth/crypto/clientauth.js +195 -0
- package/dist/oauth/crypto/clientauth.js.map +1 -0
- package/dist/oauth/crypto/codes.d.ts +65 -0
- package/dist/oauth/crypto/codes.d.ts.map +1 -0
- package/dist/oauth/crypto/codes.js +121 -0
- package/dist/oauth/crypto/codes.js.map +1 -0
- package/dist/oauth/crypto/hkdf.d.ts +13 -0
- package/dist/oauth/crypto/hkdf.d.ts.map +1 -0
- package/dist/oauth/crypto/hkdf.js +30 -0
- package/dist/oauth/crypto/hkdf.js.map +1 -0
- package/dist/oauth/crypto/keycache.d.ts +19 -0
- package/dist/oauth/crypto/keycache.d.ts.map +1 -0
- package/dist/oauth/crypto/keycache.js +44 -0
- package/dist/oauth/crypto/keycache.js.map +1 -0
- package/dist/oauth/crypto/pkce.d.ts.map +1 -0
- package/dist/oauth/{pkce.js → crypto/pkce.js} +1 -1
- package/dist/oauth/crypto/pkce.js.map +1 -0
- package/dist/oauth/{sealed.d.ts → crypto/sealed.d.ts} +12 -3
- package/dist/oauth/crypto/sealed.d.ts.map +1 -0
- package/dist/oauth/{sealed.js → crypto/sealed.js} +22 -14
- package/dist/oauth/crypto/sealed.js.map +1 -0
- package/dist/oauth/{secrethash.d.ts → crypto/secrethash.d.ts} +14 -0
- package/dist/oauth/crypto/secrethash.d.ts.map +1 -0
- package/dist/oauth/{secrethash.js → crypto/secrethash.js} +27 -11
- package/dist/oauth/crypto/secrethash.js.map +1 -0
- package/dist/oauth/deprecated.d.ts +52 -0
- package/dist/oauth/deprecated.d.ts.map +1 -0
- package/dist/oauth/deprecated.js +49 -0
- package/dist/oauth/deprecated.js.map +1 -0
- package/dist/oauth/endpoints/authorize.d.ts +3 -0
- package/dist/oauth/endpoints/authorize.d.ts.map +1 -0
- package/dist/oauth/endpoints/authorize.js +209 -0
- package/dist/oauth/endpoints/authorize.js.map +1 -0
- package/dist/oauth/endpoints/callback.d.ts +20 -0
- package/dist/oauth/endpoints/callback.d.ts.map +1 -0
- package/dist/oauth/endpoints/callback.js +31 -0
- package/dist/oauth/endpoints/callback.js.map +1 -0
- package/dist/oauth/endpoints/consent-page.d.ts +5 -0
- package/dist/oauth/endpoints/consent-page.d.ts.map +1 -0
- package/dist/oauth/endpoints/consent-page.js +63 -0
- package/dist/oauth/endpoints/consent-page.js.map +1 -0
- package/dist/oauth/endpoints/consent.d.ts +29 -0
- package/dist/oauth/endpoints/consent.d.ts.map +1 -0
- package/dist/oauth/endpoints/consent.js +98 -0
- package/dist/oauth/endpoints/consent.js.map +1 -0
- package/dist/oauth/{metadata.d.ts → endpoints/metadata.d.ts} +8 -2
- package/dist/oauth/endpoints/metadata.d.ts.map +1 -0
- package/dist/oauth/{metadata.js → endpoints/metadata.js} +10 -4
- package/dist/oauth/endpoints/metadata.js.map +1 -0
- package/dist/oauth/endpoints/register.d.ts +10 -0
- package/dist/oauth/endpoints/register.d.ts.map +1 -0
- package/dist/oauth/endpoints/register.js +96 -0
- package/dist/oauth/endpoints/register.js.map +1 -0
- package/dist/oauth/{revoke.d.ts → endpoints/revoke.d.ts} +1 -1
- package/dist/oauth/endpoints/revoke.d.ts.map +1 -0
- package/dist/oauth/{revoke.js → endpoints/revoke.js} +8 -18
- package/dist/oauth/endpoints/revoke.js.map +1 -0
- package/dist/oauth/endpoints/token.d.ts +3 -0
- package/dist/oauth/endpoints/token.d.ts.map +1 -0
- package/dist/oauth/{token.js → endpoints/token.js} +32 -25
- package/dist/oauth/endpoints/token.js.map +1 -0
- package/dist/oauth/{wellknown.d.ts → endpoints/wellknown.d.ts} +1 -1
- package/dist/oauth/endpoints/wellknown.d.ts.map +1 -0
- package/dist/oauth/{wellknown.js → endpoints/wellknown.js} +7 -9
- package/dist/oauth/endpoints/wellknown.js.map +1 -0
- package/dist/oauth/policy/redirect.d.ts.map +1 -0
- package/dist/oauth/policy/redirect.js.map +1 -0
- package/dist/oauth/policy/reqbody.d.ts +18 -0
- package/dist/oauth/policy/reqbody.d.ts.map +1 -0
- package/dist/oauth/policy/reqbody.js +68 -0
- package/dist/oauth/policy/reqbody.js.map +1 -0
- package/dist/oauth/{resource.d.ts → policy/resource.d.ts} +1 -1
- package/dist/oauth/policy/resource.d.ts.map +1 -0
- package/dist/oauth/{resource.js → policy/resource.js} +2 -2
- package/dist/oauth/policy/resource.js.map +1 -0
- package/dist/oauth/{scope.d.ts → policy/scope.d.ts} +2 -2
- package/dist/oauth/policy/scope.d.ts.map +1 -0
- package/dist/oauth/{scope.js → policy/scope.js} +3 -3
- package/dist/oauth/policy/scope.js.map +1 -0
- package/dist/oauth/router.d.ts +10 -13
- package/dist/oauth/router.d.ts.map +1 -1
- package/dist/oauth/router.js +93 -115
- package/dist/oauth/router.js.map +1 -1
- package/dist/oauth/types.d.ts +99 -45
- package/dist/oauth/types.d.ts.map +1 -1
- package/dist/oauth/types.js +1 -90
- package/dist/oauth/types.js.map +1 -1
- package/dist/server.d.ts +13 -12
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +10 -8
- package/dist/server.js.map +1 -1
- package/dist/util/defined.d.ts +11 -0
- package/dist/util/defined.d.ts.map +1 -0
- package/dist/util/defined.js +15 -0
- package/dist/util/defined.js.map +1 -0
- package/dist/util/json.d.ts +3 -0
- package/dist/util/json.d.ts.map +1 -0
- package/dist/util/json.js +3 -0
- package/dist/util/json.js.map +1 -0
- package/docs/ROADMAP.md +37 -47
- package/docs/compatibility.md +86 -0
- package/docs/diagrams/demo-tool-result.png +0 -0
- package/docs/diagrams/mcp-trellis-architecture.html +305 -0
- package/docs/guide.md +46 -16
- package/docs/reference.md +55 -22
- package/docs/security.md +58 -9
- package/docs/troubleshooting.md +19 -0
- package/package.json +27 -10
- package/dist/adapters/origins.d.ts +0 -19
- package/dist/adapters/origins.d.ts.map +0 -1
- package/dist/adapters/origins.js +0 -52
- package/dist/adapters/origins.js.map +0 -1
- package/dist/body.d.ts.map +0 -1
- package/dist/body.js.map +0 -1
- package/dist/dispatch.d.ts.map +0 -1
- package/dist/dispatch.js +0 -119
- package/dist/dispatch.js.map +0 -1
- package/dist/http.d.ts +0 -17
- package/dist/http.d.ts.map +0 -1
- package/dist/http.js +0 -38
- package/dist/http.js.map +0 -1
- package/dist/jsonrpc.d.ts.map +0 -1
- package/dist/jsonrpc.js +0 -18
- package/dist/jsonrpc.js.map +0 -1
- package/dist/methods.d.ts.map +0 -1
- package/dist/methods.js +0 -130
- package/dist/methods.js.map +0 -1
- package/dist/oauth/authorize.d.ts +0 -3
- package/dist/oauth/authorize.d.ts.map +0 -1
- package/dist/oauth/authorize.js +0 -141
- package/dist/oauth/authorize.js.map +0 -1
- package/dist/oauth/base64url.d.ts.map +0 -1
- package/dist/oauth/base64url.js.map +0 -1
- package/dist/oauth/clientauth.d.ts +0 -24
- package/dist/oauth/clientauth.d.ts.map +0 -1
- package/dist/oauth/clientauth.js +0 -119
- package/dist/oauth/clientauth.js.map +0 -1
- package/dist/oauth/codes.d.ts +0 -30
- package/dist/oauth/codes.d.ts.map +0 -1
- package/dist/oauth/codes.js +0 -85
- package/dist/oauth/codes.js.map +0 -1
- package/dist/oauth/consent.d.ts +0 -65
- package/dist/oauth/consent.d.ts.map +0 -1
- package/dist/oauth/consent.js +0 -173
- package/dist/oauth/consent.js.map +0 -1
- package/dist/oauth/metadata.d.ts.map +0 -1
- package/dist/oauth/metadata.js.map +0 -1
- package/dist/oauth/pkce.d.ts.map +0 -1
- package/dist/oauth/pkce.js.map +0 -1
- package/dist/oauth/redirect.d.ts.map +0 -1
- package/dist/oauth/redirect.js.map +0 -1
- package/dist/oauth/reqbody.d.ts +0 -10
- package/dist/oauth/reqbody.d.ts.map +0 -1
- package/dist/oauth/reqbody.js +0 -29
- package/dist/oauth/reqbody.js.map +0 -1
- package/dist/oauth/resource.d.ts.map +0 -1
- package/dist/oauth/resource.js.map +0 -1
- package/dist/oauth/revoke.d.ts.map +0 -1
- package/dist/oauth/revoke.js.map +0 -1
- package/dist/oauth/scope.d.ts.map +0 -1
- package/dist/oauth/scope.js.map +0 -1
- package/dist/oauth/sealed.d.ts.map +0 -1
- package/dist/oauth/sealed.js.map +0 -1
- package/dist/oauth/secrethash.d.ts.map +0 -1
- package/dist/oauth/secrethash.js.map +0 -1
- package/dist/oauth/token.d.ts +0 -3
- package/dist/oauth/token.d.ts.map +0 -1
- package/dist/oauth/token.js.map +0 -1
- package/dist/oauth/wellknown.d.ts.map +0 -1
- package/dist/oauth/wellknown.js.map +0 -1
- package/dist/protocol.d.ts.map +0 -1
- package/dist/protocol.js.map +0 -1
- package/dist/registry.d.ts +0 -37
- package/dist/registry.d.ts.map +0 -1
- package/dist/registry.js +0 -77
- package/dist/registry.js.map +0 -1
- package/dist/tools.d.ts.map +0 -1
- package/dist/tools.js +0 -98
- package/dist/tools.js.map +0 -1
- package/dist/validate.d.ts.map +0 -1
- package/dist/validate.js.map +0 -1
- /package/dist/oauth/{pkce.d.ts → crypto/pkce.d.ts} +0 -0
- /package/dist/oauth/{redirect.d.ts → policy/redirect.d.ts} +0 -0
- /package/dist/oauth/{redirect.js → policy/redirect.js} +0 -0
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>mcp-trellis · Architecture</title>
|
|
7
|
+
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+Hebrew:wght@400;500;600;700;800&display=swap" rel="stylesheet">
|
|
8
|
+
<style>
|
|
9
|
+
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
|
10
|
+
:root {
|
|
11
|
+
--color-paper: #f5f5fb;
|
|
12
|
+
--color-ink: #1e1f29;
|
|
13
|
+
--color-muted: #55566b;
|
|
14
|
+
--color-accent: #5b5bf0;
|
|
15
|
+
--font-sans: 'Noto Sans Hebrew', system-ui, sans-serif;
|
|
16
|
+
--font-mono: ui-monospace, 'SFMono-Regular', Menlo, Consolas, monospace;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
body {
|
|
20
|
+
font-family: var(--font-sans);
|
|
21
|
+
background: var(--color-paper);
|
|
22
|
+
color: var(--color-ink);
|
|
23
|
+
min-height: 100vh;
|
|
24
|
+
display: flex;
|
|
25
|
+
align-items: center;
|
|
26
|
+
justify-content: center;
|
|
27
|
+
padding: 3rem 2rem;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.frame { max-width: 1280px; width: 100%; }
|
|
31
|
+
|
|
32
|
+
.eyebrow {
|
|
33
|
+
font-family: var(--font-mono);
|
|
34
|
+
font-size: 0.66rem;
|
|
35
|
+
font-weight: 500;
|
|
36
|
+
letter-spacing: 0.18em;
|
|
37
|
+
text-transform: uppercase;
|
|
38
|
+
color: var(--color-muted);
|
|
39
|
+
margin-bottom: 0.5rem;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
h1 {
|
|
43
|
+
font-family: var(--font-sans);
|
|
44
|
+
font-size: clamp(1.5rem, 2.4vw + 0.75rem, 2rem);
|
|
45
|
+
font-weight: 700;
|
|
46
|
+
letter-spacing: -0.02em;
|
|
47
|
+
line-height: 1.15;
|
|
48
|
+
color: var(--color-ink);
|
|
49
|
+
margin-bottom: 1.5rem;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
svg { width: 100%; min-width: 960px; display: block; }
|
|
53
|
+
</style>
|
|
54
|
+
</head>
|
|
55
|
+
<body>
|
|
56
|
+
<div class="frame">
|
|
57
|
+
<p class="eyebrow">Architecture · mcp-trellis</p>
|
|
58
|
+
<h1>Host-agnostic MCP + OAuth 2.1</h1>
|
|
59
|
+
|
|
60
|
+
<svg viewBox="0 0 1280 760" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="mcp-trellis-architecture-title mcp-trellis-architecture-desc">
|
|
61
|
+
<title id="mcp-trellis-architecture-title">mcp-trellis architecture</title>
|
|
62
|
+
<desc id="mcp-trellis-architecture-desc">Connectors reach an edge host, then createMcpApp routes OAuth and MCP traffic to library handlers and your login, token, store, and tool ports.</desc>
|
|
63
|
+
<defs>
|
|
64
|
+
<marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#55566b"/></marker>
|
|
65
|
+
<marker id="arrow-accent" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#5b5bf0"/></marker>
|
|
66
|
+
<marker id="arrow-link" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#4545c8"/></marker>
|
|
67
|
+
</defs>
|
|
68
|
+
|
|
69
|
+
<rect width="100%" height="100%" fill="#f5f5fb"/>
|
|
70
|
+
|
|
71
|
+
<!-- Zones (before arrows) -->
|
|
72
|
+
<rect x="40" y="96" width="168" height="400" rx="8"
|
|
73
|
+
fill="rgba(30,31,41,0.02)" stroke="rgba(30,31,41,0.10)" stroke-width="0.8"/>
|
|
74
|
+
<rect x="84" y="100" width="80" height="12" rx="2" fill="#f5f5fb"/>
|
|
75
|
+
<text x="124" y="109" fill="rgba(30,31,41,0.40)" font-size="7" font-family="ui-monospace, monospace"
|
|
76
|
+
text-anchor="middle" letter-spacing="0.14em">CONNECTORS</text>
|
|
77
|
+
|
|
78
|
+
<rect x="440" y="56" width="480" height="520" rx="8"
|
|
79
|
+
fill="rgba(30,31,41,0.02)" stroke="rgba(30,31,41,0.10)" stroke-width="0.8"/>
|
|
80
|
+
<rect x="624" y="60" width="112" height="12" rx="2" fill="#f5f5fb"/>
|
|
81
|
+
<text x="680" y="69" fill="rgba(30,31,41,0.40)" font-size="7" font-family="ui-monospace, monospace"
|
|
82
|
+
text-anchor="middle" letter-spacing="0.14em">MCP-TRELLIS</text>
|
|
83
|
+
|
|
84
|
+
<rect x="980" y="96" width="260" height="440" rx="8"
|
|
85
|
+
fill="rgba(30,31,41,0.02)" stroke="rgba(30,31,41,0.10)" stroke-width="0.8"/>
|
|
86
|
+
<rect x="1052" y="100" width="116" height="12" rx="2" fill="#f5f5fb"/>
|
|
87
|
+
<text x="1110" y="109" fill="rgba(30,31,41,0.40)" font-size="7" font-family="ui-monospace, monospace"
|
|
88
|
+
text-anchor="middle" letter-spacing="0.14em">YOUR PORTS</text>
|
|
89
|
+
|
|
90
|
+
<!-- Arrows -->
|
|
91
|
+
<!-- Clients → Edge (link) -->
|
|
92
|
+
<line x1="192" y1="172" x2="248" y2="172" stroke="#4545c8" stroke-width="1.2" marker-end="url(#arrow-link)"/>
|
|
93
|
+
<line x1="192" y1="292" x2="248" y2="292" stroke="#4545c8" stroke-width="1.2" marker-end="url(#arrow-link)"/>
|
|
94
|
+
<line x1="192" y1="412" x2="248" y2="412" stroke="#4545c8" stroke-width="1.2" marker-end="url(#arrow-link)"/>
|
|
95
|
+
|
|
96
|
+
<!-- Edge → createMcpApp (accent primary) -->
|
|
97
|
+
<path d="M 392,292 H 480 Q 488,292 488,284 V 120 Q 488,112 496,112 H 592"
|
|
98
|
+
fill="none" stroke="#5b5bf0" stroke-width="1.4" marker-end="url(#arrow-accent)"/>
|
|
99
|
+
|
|
100
|
+
<!-- createMcpApp → OAuth / MCP -->
|
|
101
|
+
<path d="M 640,144 V 168 H 558 Q 550,168 550,176 V 200"
|
|
102
|
+
fill="none" stroke="#55566b" stroke-width="1.2" marker-end="url(#arrow)"/>
|
|
103
|
+
<path d="M 720,144 V 168 H 802 Q 810,168 810,176 V 200"
|
|
104
|
+
fill="none" stroke="#55566b" stroke-width="1.2" marker-end="url(#arrow)"/>
|
|
105
|
+
|
|
106
|
+
<!-- OAuth → Consent / Discovery -->
|
|
107
|
+
<line x1="550" y1="280" x2="550" y2="312" stroke="#5b5bf0" stroke-width="1.2" marker-end="url(#arrow-accent)"/>
|
|
108
|
+
<line x1="550" y1="376" x2="550" y2="408" stroke="#55566b" stroke-width="1" stroke-dasharray="4,3" marker-end="url(#arrow)"/>
|
|
109
|
+
|
|
110
|
+
<!-- MCP → Audience → Registry -->
|
|
111
|
+
<line x1="810" y1="280" x2="810" y2="312" stroke="#55566b" stroke-width="1.2" marker-end="url(#arrow)"/>
|
|
112
|
+
<line x1="810" y1="376" x2="810" y2="408" stroke="#55566b" stroke-width="1.2" marker-end="url(#arrow)"/>
|
|
113
|
+
|
|
114
|
+
<!-- Library → Ports (distinct Auth attach points: MINT@160, VERIFY@184) -->
|
|
115
|
+
<path d="M 640,228 H 680 Q 688,228 688,220 V 168 Q 688,160 696,160 H 1000"
|
|
116
|
+
fill="none" stroke="#4545c8" stroke-width="1.2" marker-end="url(#arrow-link)"/>
|
|
117
|
+
<path d="M 640,256 H 680 Q 688,256 688,264 V 288 Q 688,296 696,296 H 1000"
|
|
118
|
+
fill="none" stroke="#55566b" stroke-width="1" stroke-dasharray="4,3" marker-end="url(#arrow)"/>
|
|
119
|
+
<path d="M 900,344 H 940 Q 948,344 948,336 V 192 Q 948,184 956,184 H 1000"
|
|
120
|
+
fill="none" stroke="#55566b" stroke-width="1.2" marker-end="url(#arrow)"/>
|
|
121
|
+
<line x1="900" y1="440" x2="1000" y2="440" stroke="#55566b" stroke-width="1.2" marker-end="url(#arrow)"/>
|
|
122
|
+
|
|
123
|
+
<!-- Arrow labels (6–10px gap above stroke) -->
|
|
124
|
+
<rect x="204" y="152" width="36" height="12" rx="2" fill="#f5f5fb"/>
|
|
125
|
+
<text x="222" y="161" fill="#4545c8" font-size="8" font-family="ui-monospace, monospace" text-anchor="middle" letter-spacing="0.06em">HTTPS</text>
|
|
126
|
+
|
|
127
|
+
<rect x="500" y="92" width="48" height="12" rx="2" fill="#f5f5fb"/>
|
|
128
|
+
<text x="524" y="101" fill="#5b5bf0" font-size="8" font-family="ui-monospace, monospace" text-anchor="middle" letter-spacing="0.06em">FETCH</text>
|
|
129
|
+
|
|
130
|
+
<rect x="568" y="148" width="40" height="12" rx="2" fill="#f5f5fb"/>
|
|
131
|
+
<text x="588" y="157" fill="#55566b" font-size="8" font-family="ui-monospace, monospace" text-anchor="middle" letter-spacing="0.06em">OAUTH</text>
|
|
132
|
+
|
|
133
|
+
<rect x="744" y="148" width="32" height="12" rx="2" fill="#f5f5fb"/>
|
|
134
|
+
<text x="760" y="157" fill="#55566b" font-size="8" font-family="ui-monospace, monospace" text-anchor="middle" letter-spacing="0.06em">MCP</text>
|
|
135
|
+
|
|
136
|
+
<rect x="560" y="288" width="52" height="12" rx="2" fill="#f5f5fb"/>
|
|
137
|
+
<text x="586" y="297" fill="#5b5bf0" font-size="8" font-family="ui-monospace, monospace" text-anchor="middle" letter-spacing="0.06em">APPROVE</text>
|
|
138
|
+
|
|
139
|
+
<rect x="560" y="384" width="40" height="12" rx="2" fill="#f5f5fb"/>
|
|
140
|
+
<text x="580" y="393" fill="#8d8ea3" font-size="8" font-family="ui-monospace, monospace" text-anchor="middle" letter-spacing="0.06em">META</text>
|
|
141
|
+
|
|
142
|
+
<rect x="820" y="288" width="36" height="12" rx="2" fill="#f5f5fb"/>
|
|
143
|
+
<text x="838" y="297" fill="#55566b" font-size="8" font-family="ui-monospace, monospace" text-anchor="middle" letter-spacing="0.06em">AUD</text>
|
|
144
|
+
|
|
145
|
+
<rect x="820" y="384" width="48" height="12" rx="2" fill="#f5f5fb"/>
|
|
146
|
+
<text x="844" y="393" fill="#55566b" font-size="8" font-family="ui-monospace, monospace" text-anchor="middle" letter-spacing="0.06em">SCOPE</text>
|
|
147
|
+
|
|
148
|
+
<rect x="820" y="140" width="40" height="12" rx="2" fill="#f5f5fb"/>
|
|
149
|
+
<text x="840" y="149" fill="#4545c8" font-size="8" font-family="ui-monospace, monospace" text-anchor="middle" letter-spacing="0.06em">MINT</text>
|
|
150
|
+
|
|
151
|
+
<rect x="924" y="276" width="44" height="12" rx="2" fill="#f5f5fb"/>
|
|
152
|
+
<text x="946" y="285" fill="#8d8ea3" font-size="8" font-family="ui-monospace, monospace" text-anchor="middle" letter-spacing="0.06em">STORE</text>
|
|
153
|
+
|
|
154
|
+
<rect x="880" y="164" width="48" height="12" rx="2" fill="#f5f5fb"/>
|
|
155
|
+
<text x="904" y="173" fill="#55566b" font-size="8" font-family="ui-monospace, monospace" text-anchor="middle" letter-spacing="0.06em">VERIFY</text>
|
|
156
|
+
|
|
157
|
+
<rect x="928" y="420" width="40" height="12" rx="2" fill="#f5f5fb"/>
|
|
158
|
+
<text x="948" y="429" fill="#55566b" font-size="8" font-family="ui-monospace, monospace" text-anchor="middle" letter-spacing="0.06em">CALL</text>
|
|
159
|
+
|
|
160
|
+
<!-- Nodes: Connectors -->
|
|
161
|
+
<rect x="56" y="140" width="136" height="64" rx="6" fill="#f5f5fb"/>
|
|
162
|
+
<rect x="56" y="140" width="136" height="64" rx="6" fill="rgba(85,86,107,0.10)" stroke="#8d8ea3" stroke-width="1"/>
|
|
163
|
+
<rect x="64" y="148" width="40" height="12" rx="2" fill="transparent" stroke="rgba(141,142,163,0.40)" stroke-width="0.8"/>
|
|
164
|
+
<text x="84" y="157" fill="#8d8ea3" font-size="7" font-family="ui-monospace, monospace" text-anchor="middle" letter-spacing="0.08em">CLIENT</text>
|
|
165
|
+
<text x="124" y="176" fill="#1e1f29" font-size="12" font-weight="600" font-family="'Noto Sans Hebrew', sans-serif" text-anchor="middle">Claude</text>
|
|
166
|
+
<text x="124" y="192" fill="#55566b" font-size="9" font-family="ui-monospace, monospace" text-anchor="middle">DCR + PKCE</text>
|
|
167
|
+
|
|
168
|
+
<rect x="56" y="260" width="136" height="64" rx="6" fill="#f5f5fb"/>
|
|
169
|
+
<rect x="56" y="260" width="136" height="64" rx="6" fill="rgba(85,86,107,0.10)" stroke="#8d8ea3" stroke-width="1"/>
|
|
170
|
+
<rect x="64" y="268" width="40" height="12" rx="2" fill="transparent" stroke="rgba(141,142,163,0.40)" stroke-width="0.8"/>
|
|
171
|
+
<text x="84" y="277" fill="#8d8ea3" font-size="7" font-family="ui-monospace, monospace" text-anchor="middle" letter-spacing="0.08em">CLIENT</text>
|
|
172
|
+
<text x="124" y="296" fill="#1e1f29" font-size="12" font-weight="600" font-family="'Noto Sans Hebrew', sans-serif" text-anchor="middle">Gemini</text>
|
|
173
|
+
<text x="124" y="312" fill="#55566b" font-size="9" font-family="ui-monospace, monospace" text-anchor="middle">pre-reg secret</text>
|
|
174
|
+
|
|
175
|
+
<rect x="56" y="380" width="136" height="64" rx="6" fill="#f5f5fb"/>
|
|
176
|
+
<rect x="56" y="380" width="136" height="64" rx="6" fill="rgba(85,86,107,0.10)" stroke="#8d8ea3" stroke-width="1"/>
|
|
177
|
+
<rect x="64" y="388" width="40" height="12" rx="2" fill="transparent" stroke="rgba(141,142,163,0.40)" stroke-width="0.8"/>
|
|
178
|
+
<text x="84" y="397" fill="#8d8ea3" font-size="7" font-family="ui-monospace, monospace" text-anchor="middle" letter-spacing="0.08em">CLIENT</text>
|
|
179
|
+
<text x="124" y="416" fill="#1e1f29" font-size="12" font-weight="600" font-family="'Noto Sans Hebrew', sans-serif" text-anchor="middle">Codex</text>
|
|
180
|
+
<text x="124" y="432" fill="#55566b" font-size="9" font-family="ui-monospace, monospace" text-anchor="middle">OAuth 2.1 PKCE</text>
|
|
181
|
+
|
|
182
|
+
<!-- Edge host -->
|
|
183
|
+
<rect x="248" y="148" width="144" height="320" rx="6" fill="#f5f5fb"/>
|
|
184
|
+
<rect x="248" y="148" width="144" height="320" rx="6" fill="rgba(30,31,41,0.03)" stroke="rgba(30,31,41,0.30)" stroke-width="1"/>
|
|
185
|
+
<rect x="256" y="156" width="36" height="12" rx="2" fill="transparent" stroke="rgba(30,31,41,0.22)" stroke-width="0.8"/>
|
|
186
|
+
<text x="274" y="165" fill="#8d8ea3" font-size="7" font-family="ui-monospace, monospace" text-anchor="middle" letter-spacing="0.08em">EDGE</text>
|
|
187
|
+
<text x="320" y="292" fill="#1e1f29" font-size="12" font-weight="600" font-family="'Noto Sans Hebrew', sans-serif" text-anchor="middle">Your host</text>
|
|
188
|
+
<text x="320" y="312" fill="#55566b" font-size="9" font-family="ui-monospace, monospace" text-anchor="middle">Workers · Next</text>
|
|
189
|
+
<text x="320" y="328" fill="#55566b" font-size="9" font-family="ui-monospace, monospace" text-anchor="middle">Node · Deno · Bun</text>
|
|
190
|
+
<text x="320" y="352" fill="#8d8ea3" font-size="8" font-family="ui-monospace, monospace" text-anchor="middle">Request → Response</text>
|
|
191
|
+
|
|
192
|
+
<!-- createMcpApp (focal) -->
|
|
193
|
+
<rect x="592" y="80" width="176" height="64" rx="6" fill="#f5f5fb"/>
|
|
194
|
+
<rect x="592" y="80" width="176" height="64" rx="6" fill="#efeeff" stroke="#5b5bf0" stroke-width="1"/>
|
|
195
|
+
<rect x="600" y="88" width="36" height="12" rx="2" fill="transparent" stroke="rgba(91,91,240,0.50)" stroke-width="0.8"/>
|
|
196
|
+
<text x="618" y="97" fill="#5b5bf0" font-size="7" font-family="ui-monospace, monospace" text-anchor="middle" letter-spacing="0.08em">APP</text>
|
|
197
|
+
<text x="680" y="116" fill="#1e1f29" font-size="12" font-weight="600" font-family="'Noto Sans Hebrew', sans-serif" text-anchor="middle">createMcpApp</text>
|
|
198
|
+
<text x="680" y="132" fill="#55566b" font-size="9" font-family="ui-monospace, monospace" text-anchor="middle">oauth.tryHandle → /mcp</text>
|
|
199
|
+
|
|
200
|
+
<!-- OAuth AS -->
|
|
201
|
+
<rect x="460" y="200" width="180" height="80" rx="6" fill="#f5f5fb"/>
|
|
202
|
+
<rect x="460" y="200" width="180" height="80" rx="6" fill="#ffffff" stroke="#1e1f29" stroke-width="1"/>
|
|
203
|
+
<rect x="468" y="208" width="28" height="12" rx="2" fill="transparent" stroke="rgba(30,31,41,0.40)" stroke-width="0.8"/>
|
|
204
|
+
<text x="482" y="217" fill="#1e1f29" font-size="7" font-family="ui-monospace, monospace" text-anchor="middle" letter-spacing="0.08em">AS</text>
|
|
205
|
+
<text x="550" y="240" fill="#1e1f29" font-size="12" font-weight="600" font-family="'Noto Sans Hebrew', sans-serif" text-anchor="middle">OAuth router</text>
|
|
206
|
+
<text x="550" y="256" fill="#55566b" font-size="9" font-family="ui-monospace, monospace" text-anchor="middle">/authorize · /token</text>
|
|
207
|
+
<text x="550" y="268" fill="#55566b" font-size="9" font-family="ui-monospace, monospace" text-anchor="middle">/register · /revoke</text>
|
|
208
|
+
|
|
209
|
+
<!-- Consent (security, 2nd accent) -->
|
|
210
|
+
<rect x="460" y="312" width="180" height="64" rx="6" fill="#f5f5fb"/>
|
|
211
|
+
<rect x="460" y="312" width="180" height="64" rx="6" fill="rgba(91,91,240,0.05)" stroke="rgba(91,91,240,0.50)" stroke-width="1" stroke-dasharray="4,4"/>
|
|
212
|
+
<rect x="468" y="320" width="48" height="12" rx="2" fill="transparent" stroke="rgba(91,91,240,0.40)" stroke-width="0.8"/>
|
|
213
|
+
<text x="492" y="329" fill="#5b5bf0" font-size="7" font-family="ui-monospace, monospace" text-anchor="middle" letter-spacing="0.08em">SECURE</text>
|
|
214
|
+
<text x="550" y="348" fill="#1e1f29" font-size="12" font-weight="600" font-family="'Noto Sans Hebrew', sans-serif" text-anchor="middle">Consent</text>
|
|
215
|
+
<text x="550" y="364" fill="#55566b" font-size="9" font-family="ui-monospace, monospace" text-anchor="middle">POST …/consent</text>
|
|
216
|
+
|
|
217
|
+
<!-- Discovery -->
|
|
218
|
+
<rect x="460" y="408" width="180" height="64" rx="6" fill="#f5f5fb"/>
|
|
219
|
+
<rect x="460" y="408" width="180" height="64" rx="6" fill="rgba(30,31,41,0.02)" stroke="rgba(30,31,41,0.20)" stroke-width="1" stroke-dasharray="4,3"/>
|
|
220
|
+
<rect x="468" y="416" width="36" height="12" rx="2" fill="transparent" stroke="rgba(30,31,41,0.25)" stroke-width="0.8"/>
|
|
221
|
+
<text x="486" y="425" fill="#8d8ea3" font-size="7" font-family="ui-monospace, monospace" text-anchor="middle" letter-spacing="0.08em">META</text>
|
|
222
|
+
<text x="550" y="444" fill="#1e1f29" font-size="12" font-weight="600" font-family="'Noto Sans Hebrew', sans-serif" text-anchor="middle">Discovery</text>
|
|
223
|
+
<text x="550" y="460" fill="#55566b" font-size="9" font-family="ui-monospace, monospace" text-anchor="middle">.well-known/*</text>
|
|
224
|
+
|
|
225
|
+
<!-- MCP Handler -->
|
|
226
|
+
<rect x="720" y="200" width="180" height="80" rx="6" fill="#f5f5fb"/>
|
|
227
|
+
<rect x="720" y="200" width="180" height="80" rx="6" fill="#ffffff" stroke="#1e1f29" stroke-width="1"/>
|
|
228
|
+
<rect x="728" y="208" width="36" height="12" rx="2" fill="transparent" stroke="rgba(30,31,41,0.40)" stroke-width="0.8"/>
|
|
229
|
+
<text x="746" y="217" fill="#1e1f29" font-size="7" font-family="ui-monospace, monospace" text-anchor="middle" letter-spacing="0.08em">MCP</text>
|
|
230
|
+
<text x="810" y="240" fill="#1e1f29" font-size="12" font-weight="600" font-family="'Noto Sans Hebrew', sans-serif" text-anchor="middle">MCP handler</text>
|
|
231
|
+
<text x="810" y="256" fill="#55566b" font-size="9" font-family="ui-monospace, monospace" text-anchor="middle">JSON-RPC /mcp</text>
|
|
232
|
+
<text x="810" y="268" fill="#55566b" font-size="9" font-family="ui-monospace, monospace" text-anchor="middle">initialize · tools/*</text>
|
|
233
|
+
|
|
234
|
+
<!-- Audience gate (ink dashed — accent reserved for createMcpApp + Consent) -->
|
|
235
|
+
<rect x="720" y="312" width="180" height="64" rx="6" fill="#f5f5fb"/>
|
|
236
|
+
<rect x="720" y="312" width="180" height="64" rx="6" fill="rgba(30,31,41,0.02)" stroke="rgba(30,31,41,0.30)" stroke-width="1" stroke-dasharray="4,4"/>
|
|
237
|
+
<rect x="728" y="320" width="36" height="12" rx="2" fill="transparent" stroke="rgba(30,31,41,0.30)" stroke-width="0.8"/>
|
|
238
|
+
<text x="746" y="329" fill="#55566b" font-size="7" font-family="ui-monospace, monospace" text-anchor="middle" letter-spacing="0.08em">GATE</text>
|
|
239
|
+
<text x="810" y="348" fill="#1e1f29" font-size="12" font-weight="600" font-family="'Noto Sans Hebrew', sans-serif" text-anchor="middle">Audience check</text>
|
|
240
|
+
<text x="810" y="364" fill="#55566b" font-size="9" font-family="ui-monospace, monospace" text-anchor="middle">RFC 8707 aud</text>
|
|
241
|
+
|
|
242
|
+
<!-- Tool registry -->
|
|
243
|
+
<rect x="720" y="408" width="180" height="64" rx="6" fill="#f5f5fb"/>
|
|
244
|
+
<rect x="720" y="408" width="180" height="64" rx="6" fill="rgba(30,31,41,0.05)" stroke="#55566b" stroke-width="1"/>
|
|
245
|
+
<rect x="728" y="416" width="40" height="12" rx="2" fill="transparent" stroke="rgba(85,86,107,0.50)" stroke-width="0.8"/>
|
|
246
|
+
<text x="748" y="425" fill="#55566b" font-size="7" font-family="ui-monospace, monospace" text-anchor="middle" letter-spacing="0.08em">REG</text>
|
|
247
|
+
<text x="810" y="444" fill="#1e1f29" font-size="12" font-weight="600" font-family="'Noto Sans Hebrew', sans-serif" text-anchor="middle">Tool registry</text>
|
|
248
|
+
<text x="810" y="460" fill="#55566b" font-size="9" font-family="ui-monospace, monospace" text-anchor="middle">scope-gated call</text>
|
|
249
|
+
|
|
250
|
+
<!-- Your ports -->
|
|
251
|
+
<rect x="1000" y="140" width="220" height="72" rx="6" fill="#f5f5fb"/>
|
|
252
|
+
<rect x="1000" y="140" width="220" height="72" rx="6" fill="rgba(85,86,107,0.10)" stroke="#8d8ea3" stroke-width="1"/>
|
|
253
|
+
<rect x="1008" y="148" width="40" height="12" rx="2" fill="transparent" stroke="rgba(141,142,163,0.40)" stroke-width="0.8"/>
|
|
254
|
+
<text x="1028" y="157" fill="#8d8ea3" font-size="7" font-family="ui-monospace, monospace" text-anchor="middle" letter-spacing="0.08em">AUTH</text>
|
|
255
|
+
<text x="1110" y="176" fill="#1e1f29" font-size="12" font-weight="600" font-family="'Noto Sans Hebrew', sans-serif" text-anchor="middle">Auth ports</text>
|
|
256
|
+
<text x="1110" y="192" fill="#55566b" font-size="9" font-family="ui-monospace, monospace" text-anchor="middle">resolve · mint · verify</text>
|
|
257
|
+
|
|
258
|
+
<rect x="1000" y="260" width="220" height="72" rx="6" fill="#f5f5fb"/>
|
|
259
|
+
<rect x="1000" y="260" width="220" height="72" rx="6" fill="rgba(30,31,41,0.05)" stroke="#55566b" stroke-width="1"/>
|
|
260
|
+
<rect x="1008" y="268" width="44" height="12" rx="2" fill="transparent" stroke="rgba(85,86,107,0.50)" stroke-width="0.8"/>
|
|
261
|
+
<text x="1030" y="277" fill="#55566b" font-size="7" font-family="ui-monospace, monospace" text-anchor="middle" letter-spacing="0.08em">STORE</text>
|
|
262
|
+
<text x="1110" y="296" fill="#1e1f29" font-size="12" font-weight="600" font-family="'Noto Sans Hebrew', sans-serif" text-anchor="middle">Stores</text>
|
|
263
|
+
<text x="1110" y="312" fill="#55566b" font-size="9" font-family="ui-monospace, monospace" text-anchor="middle">clientStore · codeStore</text>
|
|
264
|
+
|
|
265
|
+
<rect x="1000" y="380" width="220" height="72" rx="6" fill="#f5f5fb"/>
|
|
266
|
+
<rect x="1000" y="380" width="220" height="72" rx="6" fill="#ffffff" stroke="#1e1f29" stroke-width="1"/>
|
|
267
|
+
<rect x="1008" y="388" width="40" height="12" rx="2" fill="transparent" stroke="rgba(30,31,41,0.40)" stroke-width="0.8"/>
|
|
268
|
+
<text x="1028" y="397" fill="#1e1f29" font-size="7" font-family="ui-monospace, monospace" text-anchor="middle" letter-spacing="0.08em">TOOLS</text>
|
|
269
|
+
<text x="1110" y="416" fill="#1e1f29" font-size="12" font-weight="600" font-family="'Noto Sans Hebrew', sans-serif" text-anchor="middle">Tool handlers</text>
|
|
270
|
+
<text x="1110" y="432" fill="#55566b" font-size="9" font-family="ui-monospace, monospace" text-anchor="middle">your business logic</text>
|
|
271
|
+
|
|
272
|
+
<!-- Legend -->
|
|
273
|
+
<line x1="40" y1="640" x2="1240" y2="640" stroke="rgba(30,31,41,0.10)" stroke-width="0.8"/>
|
|
274
|
+
<text x="40" y="660" fill="#55566b" font-size="8" font-family="ui-monospace, monospace" letter-spacing="0.14em">LEGEND</text>
|
|
275
|
+
|
|
276
|
+
<rect x="40" y="676" width="14" height="10" rx="2" fill="#efeeff" stroke="#5b5bf0" stroke-width="1"/>
|
|
277
|
+
<text x="60" y="684" fill="#55566b" font-size="8" font-family="'Noto Sans Hebrew', sans-serif">Focal router</text>
|
|
278
|
+
|
|
279
|
+
<rect x="168" y="676" width="14" height="10" rx="2" fill="#ffffff" stroke="#1e1f29" stroke-width="1"/>
|
|
280
|
+
<text x="188" y="684" fill="#55566b" font-size="8" font-family="'Noto Sans Hebrew', sans-serif">Library handler</text>
|
|
281
|
+
|
|
282
|
+
<rect x="316" y="676" width="14" height="10" rx="2" fill="rgba(91,91,240,0.05)" stroke="rgba(91,91,240,0.50)" stroke-width="1" stroke-dasharray="3,2"/>
|
|
283
|
+
<text x="336" y="684" fill="#55566b" font-size="8" font-family="'Noto Sans Hebrew', sans-serif">Security control</text>
|
|
284
|
+
|
|
285
|
+
<rect x="468" y="676" width="14" height="10" rx="2" fill="rgba(30,31,41,0.05)" stroke="#55566b" stroke-width="1"/>
|
|
286
|
+
<text x="488" y="684" fill="#55566b" font-size="8" font-family="'Noto Sans Hebrew', sans-serif">Store / registry</text>
|
|
287
|
+
|
|
288
|
+
<rect x="620" y="676" width="14" height="10" rx="2" fill="rgba(30,31,41,0.03)" stroke="rgba(30,31,41,0.30)" stroke-width="1"/>
|
|
289
|
+
<text x="640" y="684" fill="#55566b" font-size="8" font-family="'Noto Sans Hebrew', sans-serif">Edge host</text>
|
|
290
|
+
|
|
291
|
+
<rect x="732" y="676" width="14" height="10" rx="2" fill="rgba(85,86,107,0.10)" stroke="#8d8ea3" stroke-width="1"/>
|
|
292
|
+
<text x="752" y="684" fill="#55566b" font-size="8" font-family="'Noto Sans Hebrew', sans-serif">External / port</text>
|
|
293
|
+
|
|
294
|
+
<line x1="880" y1="680" x2="908" y2="680" stroke="#5b5bf0" stroke-width="1.4" marker-end="url(#arrow-accent)"/>
|
|
295
|
+
<text x="916" y="684" fill="#55566b" font-size="8" font-family="'Noto Sans Hebrew', sans-serif">Primary</text>
|
|
296
|
+
|
|
297
|
+
<line x1="1000" y1="680" x2="1028" y2="680" stroke="#4545c8" stroke-width="1.2" marker-end="url(#arrow-link)"/>
|
|
298
|
+
<text x="1036" y="684" fill="#55566b" font-size="8" font-family="'Noto Sans Hebrew', sans-serif">HTTP / mint</text>
|
|
299
|
+
|
|
300
|
+
<line x1="1140" y1="680" x2="1168" y2="680" stroke="#55566b" stroke-width="1" stroke-dasharray="4,3" marker-end="url(#arrow)"/>
|
|
301
|
+
<text x="1176" y="684" fill="#55566b" font-size="8" font-family="'Noto Sans Hebrew', sans-serif">Optional</text>
|
|
302
|
+
</svg>
|
|
303
|
+
</div>
|
|
304
|
+
</body>
|
|
305
|
+
</html>
|
package/docs/guide.md
CHANGED
|
@@ -2,8 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
Practical deep dive: architecture, host recipes, ports, tools, and multi-tenant
|
|
4
4
|
connectors. For a working minimal server, start from the [README](../README.md).
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
The **canonical example** is [`examples/project-desk`](../examples/project-desk/)
|
|
6
|
+
(Project desk: login → consent → user-scoped tools; local docs in
|
|
7
|
+
[`examples/saas-demo`](../examples/saas-demo/)). API tables and exports live
|
|
8
|
+
in [reference.md](reference.md). Security guarantees and threat model:
|
|
9
|
+
[security.md](security.md).
|
|
7
10
|
|
|
8
11
|
[Architecture](#how-it-fits-together) · [Clients](#clients) · [Recipes](#recipes) ·
|
|
9
12
|
[Compose the primitives](#advanced-compose-the-primitives) ·
|
|
@@ -69,7 +72,7 @@ registration.
|
|
|
69
72
|
// Worker
|
|
70
73
|
export default { fetch: (req: Request, env: Env) => buildApp(env).fetch(req) };
|
|
71
74
|
|
|
72
|
-
// Next.js App Router —
|
|
75
|
+
// Next.js App Router — see examples/nextjs-saas/
|
|
73
76
|
export const GET = (req: Request) => app.fetch(req);
|
|
74
77
|
export const POST = (req: Request) => app.fetch(req);
|
|
75
78
|
export const OPTIONS = (req: Request) => app.fetch(req);
|
|
@@ -181,7 +184,7 @@ Also mount `.well-known/*` and `/mcp/oauth/*` the same way (or route everything
|
|
|
181
184
|
|
|
182
185
|
Express, Cloud Functions, Cloud Run, `http.createServer` — bridge with
|
|
183
186
|
`asNodeHandler`. Runnable recipe: [`examples/http-server.ts`](../examples/http-server.ts)
|
|
184
|
-
(`npx tsx examples/http-server.ts`).
|
|
187
|
+
(set `MCP_SECRET`, e.g. from `openssl rand -base64 32`, then `npx tsx examples/http-server.ts`).
|
|
185
188
|
|
|
186
189
|
## Ports — what you implement
|
|
187
190
|
|
|
@@ -191,18 +194,22 @@ The library stays protocol-shaped. Your app plugs in the seams:
|
|
|
191
194
|
|
|
192
195
|
### App (`createMcpApp`)
|
|
193
196
|
|
|
197
|
+
Prefer `signedTokenAuth({ secret, resolveUser, loginUrl, codeStore })` to fill
|
|
198
|
+
`codeSecret` / `mintAccessToken` / `verifyToken` from one secret. The table
|
|
199
|
+
below is the advanced port surface when you outgrow the helper.
|
|
200
|
+
|
|
194
201
|
| Port | Role |
|
|
195
202
|
|------|------|
|
|
196
203
|
| `verifyToken(token, req)` | Decode a bearer and return `{ userId, scopes, audience, claims? }`, or `null`. **The library compares `audience` against this server's canonical resource** — you cannot forget the check. Optional `claims` are passed to `context` on `principal` |
|
|
197
204
|
| `resolveUser`, `loginUrl`, `mintAccessToken`, `codeSecret` | Same as the OAuth ports below |
|
|
198
205
|
| `clientStore?` | Pre-registered clients; required for confidential clients like Gemini |
|
|
199
|
-
| `refreshAccessToken?` | If set, metadata advertises `refresh_token` |
|
|
206
|
+
| `refreshAccessToken?` | If set, metadata advertises `refresh_token`. Receives `resource` and optional reduced `scope` — **MUST reject tokens not originally issued for that resource, and any `scope` outside the originally granted set** (see [security.md](security.md)) |
|
|
200
207
|
| `revokeToken?` | RFC 7009; presence mounts `/revoke` and advertises `revocation_endpoint` |
|
|
201
208
|
|
|
202
209
|
`consent?` (approval-page policy — see [Consent](#consent), below) and
|
|
203
210
|
`defaultScopes?` sit as top-level `McpAppOptions`, not under `auth` — they
|
|
204
211
|
are policy, not credentials, the same reasoning as `allowLoopback`.
|
|
205
|
-
| `context?`, `audit?` |
|
|
212
|
+
| `context?`, `audit?` | `context` defaults to `{}`. Top-level `audit` is a **unified** sink for MCP and OAuth (`entry.source` is `"mcp"` or `"oauth"`). `auth.audit` overrides OAuth delivery when both are set |
|
|
206
213
|
|
|
207
214
|
### MCP (`createMcpHandler`)
|
|
208
215
|
|
|
@@ -213,7 +220,7 @@ The lower-level handler. Here the audience check is **yours** — prefer
|
|
|
213
220
|
|------|------|
|
|
214
221
|
| `authenticate(req, method, tool?)` | Return `{ id, scopes, claims? }`, or `null` → 401 + `WWW-Authenticate`. **Must reject tokens whose audience is not this server's canonical resource** |
|
|
215
222
|
| `context(req, principal)` | Build per-request ctx for tools (DB, env, …). Use `principal?.claims` for tenant / plan / role without re-decoding the bearer |
|
|
216
|
-
| `audit?(entry)` | Opt-in **metrics hook**: pass any function to receive tool results **and** auth denials (bad token, missing scope, query-string token), plus the 500 path when a host port throws. `entry.method` is `""` for transport-level denials made before parsing. Protocol errors (malformed JSON, bad `jsonrpc`, unsupported protocol version, oversized body, batch) are **not** audited. Throwing from this port never fails the request, and neither does hanging — see `auditTimeoutMs` below. Omit it and the library stays silent |
|
|
223
|
+
| `audit?(entry)` | Opt-in **metrics hook**: pass any function to receive tool results **and** auth denials (bad token, missing scope, query-string token, rejected browser Origin), plus the 500 path when a host port throws. `entry.method` is `""` for transport-level denials made before parsing (`query_string_token`, `unauthorized`, `origin_not_allowed`). Protocol errors (malformed JSON, bad `jsonrpc`, unsupported protocol version, oversized body, batch) are **not** audited. Throwing from this port never fails the request, and neither does hanging — see `auditTimeoutMs` below. Omit it and the library stays silent |
|
|
217
224
|
|
|
218
225
|
`auditTimeoutMs` (default 1000ms) races `audit` against a timeout, so a
|
|
219
226
|
slow sink can't stall a response past that bound either.
|
|
@@ -233,14 +240,14 @@ createMcpApp({ /* … */, audit: consoleAudit });
|
|
|
233
240
|
createMcpApp({
|
|
234
241
|
/* … */,
|
|
235
242
|
audit: (entry) => {
|
|
236
|
-
// entry
|
|
243
|
+
// entry.source === "mcp" | "oauth"
|
|
237
244
|
void metrics.record(entry);
|
|
238
245
|
},
|
|
239
246
|
});
|
|
240
247
|
```
|
|
241
248
|
|
|
242
|
-
Failures (denials and tool exceptions) go to `console.error` when using
|
|
243
|
-
`consoleAudit`;
|
|
249
|
+
Failures (MCP denials and tool exceptions) go to `console.error` when using
|
|
250
|
+
`consoleAudit`; MCP successes and OAuth events go to `console.log`. Entries never carry raw
|
|
244
251
|
exceptions or stack traces, so console output is safe. For anything beyond
|
|
245
252
|
stdout, write your own `audit` function — that is the intended production path.
|
|
246
253
|
|
|
@@ -248,15 +255,21 @@ stdout, write your own `audit` function — that is the intended production path
|
|
|
248
255
|
|
|
249
256
|
By default `initialize`, `ping`, and notifications are public. Override `publicMethods` if every method must require Bearer.
|
|
250
257
|
|
|
258
|
+
**Browser `Origin`.** MCP Streamable HTTP expects servers to validate the
|
|
259
|
+
request `Origin` header. Pass `allowedRequestOrigins` on `createMcpHandler` /
|
|
260
|
+
`createMcpApp`. Native connectors omit the header and are admitted. An omitted
|
|
261
|
+
allowlist **rejects** any present `Origin` (use `["*"]` only if you mean it).
|
|
262
|
+
This is separate from Node Host `allowedOrigins` on `asNodeHandler`.
|
|
263
|
+
|
|
251
264
|
### OAuth (`createOAuthRouter`)
|
|
252
265
|
|
|
253
266
|
| Port | Role |
|
|
254
267
|
|------|------|
|
|
255
|
-
| `codeSecret` |
|
|
268
|
+
| `codeSecret` | Secret(s) sealing auth codes, consent tickets, and DCR client assertions, and keying `secretHash` (string, `string[]`, or `(req) => string \| string[]`). A single string works as before; pass an array to rotate keys — see [security.md](security.md#rotating-codesecret) |
|
|
256
269
|
| `resolveUser` | Consenting user, or `null` → redirect to `loginUrl` |
|
|
257
270
|
| `loginUrl` | Where unauthenticated authorize requests go |
|
|
258
271
|
| `mintAccessToken` | Issue a **user-bound**, **audience-bound** access token (`resource` is the RFC 8707 URI) — never a shared god token |
|
|
259
|
-
| `refreshAccessToken?` | If set, metadata advertises `refresh_token`;
|
|
272
|
+
| `refreshAccessToken?` | If set, metadata advertises `refresh_token`; receives `resource` and optional client `scope` (advertised-scope check is library-side). **MUST reject refresh tokens not originally issued for that `resource`, and any `scope` outside the originally granted set** — opaque RT, same pattern as audience |
|
|
260
273
|
| `revokeToken?` | If set, mounts `/revoke` and advertises `revocation_endpoint`. Well-formed authenticated revoke → 200 even if the token is unknown; `invalid_request` 400 and `invalid_client` 401 still apply |
|
|
261
274
|
| `codeStore?` | Shared single-use jti store for multi-instance (`consume(jti, expMs)`); pruning in-memory default otherwise. Also backs consent-ticket single-use — see below |
|
|
262
275
|
| `clientStore?` | Pre-registered clients: `get(clientId)` returns registered redirect URIs and auth method. Two ways to authenticate a confidential client's secret — **prefer `secretHash(clientId)`**: return a stored hash from `hashClientSecret`, and the library compares it with the same constant-time primitive it uses everywhere else; `verifySecret(clientId, presented)` is the fallback when you'd rather compare yourself. Credentials never enter the library either way |
|
|
@@ -315,17 +328,25 @@ createToolRegistry(tools, { validateArgs: false }) // default: off, easy adoptio
|
|
|
315
328
|
```
|
|
316
329
|
|
|
317
330
|
- Handler may return a `string` or `{ content, isError? }`
|
|
318
|
-
-
|
|
331
|
+
- A thrown handler exception becomes `isError: true` (not a transport error)
|
|
332
|
+
- `registry.call(name, ...)` itself returns `isError: true` for an unknown
|
|
333
|
+
`name` too — but the JSON-RPC `tools/call` dispatch (`createMcpHandler` /
|
|
334
|
+
`createMcpApp`) checks the name against the registry *before* calling it,
|
|
335
|
+
and answers an unrecognized one with a protocol-level `-32602` error
|
|
336
|
+
instead: MCP distinguishes "this request doesn't refer to a real tool"
|
|
337
|
+
from a tool's own execution outcome. The registry's `isError: true`
|
|
338
|
+
fallback only surfaces to a caller that invokes `registry.call` directly,
|
|
339
|
+
outside that dispatch.
|
|
319
340
|
- Thrown exceptions are **redacted** by default (`"Tool execution failed"`); pass `onToolError` to map them. An `onToolError` that itself throws or returns a non-string falls back to the redacted default
|
|
320
341
|
- Duplicate tool names throw at registry construction
|
|
321
342
|
- Turn `validateArgs: true` once clients send schema-valid args. The evaluated
|
|
322
343
|
subset is `type`, `enum`, `required`, `properties`, `items`, `minimum`,
|
|
323
|
-
`maximum`. Pure metadata (`description`, `title`, `$schema`, `$id`,
|
|
344
|
+
`maximum`, and boolean `additionalProperties`. Pure metadata (`description`, `title`, `$schema`, `$id`,
|
|
324
345
|
`$comment`, `default`, `examples`, `deprecated`, `readOnly`, `writeOnly`,
|
|
325
346
|
`format`) is allowed and never evaluated. Any other keyword is not
|
|
326
347
|
evaluated — and with `validateArgs: true` `createToolRegistry` throws at
|
|
327
|
-
construction so a schema like `pattern` or
|
|
328
|
-
silently look enforced
|
|
348
|
+
construction so a schema like `pattern` or a schema-valued
|
|
349
|
+
`additionalProperties` cannot silently look enforced
|
|
329
350
|
|
|
330
351
|
### Wrapping an API as a tool
|
|
331
352
|
|
|
@@ -370,6 +391,15 @@ const getWeather = apiTool({
|
|
|
370
391
|
echoes back). Pass `onError(res)` to shape it yourself, e.g. include a
|
|
371
392
|
redacted version of the body. `fetch` is overridable — testing, request
|
|
372
393
|
signing, a custom agent.
|
|
394
|
+
- **`timeoutMs`** (default `30000`) aborts the upstream call past that many
|
|
395
|
+
ms — an upstream that never responds otherwise hangs the tool call (and
|
|
396
|
+
the MCP request behind it) indefinitely. Pass `false` to disable; a
|
|
397
|
+
timeout firing surfaces as `isError: true` with a clear message, not a
|
|
398
|
+
thrown exception `onToolError` would redact.
|
|
399
|
+
- **`maxResponseBytes`** (default 1 MiB) caps the upstream response body
|
|
400
|
+
before `respond`/`onError` ever see it — the same memory-exhaustion shape
|
|
401
|
+
an unbounded *incoming* request body is. Exceeding it also surfaces as
|
|
402
|
+
`isError: true`, not a thrown exception.
|
|
373
403
|
- `defineTool` alone (without `request`/`respond`) is just the typed-args
|
|
374
404
|
layer over a regular `ToolDef` — use it for anything, not only REST calls.
|
|
375
405
|
|