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.
Files changed (301) hide show
  1. package/README.md +65 -93
  2. package/dist/adapters/node-request.d.ts +53 -0
  3. package/dist/adapters/node-request.d.ts.map +1 -0
  4. package/dist/adapters/node-request.js +165 -0
  5. package/dist/adapters/node-request.js.map +1 -0
  6. package/dist/adapters/node.d.ts +13 -30
  7. package/dist/adapters/node.d.ts.map +1 -1
  8. package/dist/adapters/node.js +55 -101
  9. package/dist/adapters/node.js.map +1 -1
  10. package/dist/advanced.d.ts +18 -0
  11. package/dist/advanced.d.ts.map +1 -0
  12. package/dist/advanced.js +18 -0
  13. package/dist/advanced.js.map +1 -0
  14. package/dist/app-options.d.ts +132 -0
  15. package/dist/app-options.d.ts.map +1 -0
  16. package/dist/app-options.js +2 -0
  17. package/dist/app-options.js.map +1 -0
  18. package/dist/app.d.ts +2 -89
  19. package/dist/app.d.ts.map +1 -1
  20. package/dist/app.js +143 -63
  21. package/dist/app.js.map +1 -1
  22. package/dist/audit.d.ts +5 -5
  23. package/dist/audit.d.ts.map +1 -1
  24. package/dist/audit.js +19 -8
  25. package/dist/audit.js.map +1 -1
  26. package/dist/auth/bearer.d.ts +4 -1
  27. package/dist/auth/bearer.d.ts.map +1 -1
  28. package/dist/auth/bearer.js +19 -4
  29. package/dist/auth/bearer.js.map +1 -1
  30. package/dist/auth/signed-token.d.ts +26 -0
  31. package/dist/auth/signed-token.d.ts.map +1 -0
  32. package/dist/auth/signed-token.js +96 -0
  33. package/dist/auth/signed-token.js.map +1 -0
  34. package/dist/clients.js +1 -1
  35. package/dist/clients.js.map +1 -1
  36. package/dist/deprecated.d.ts +42 -0
  37. package/dist/deprecated.d.ts.map +1 -0
  38. package/dist/deprecated.js +35 -0
  39. package/dist/deprecated.js.map +1 -0
  40. package/dist/{body.d.ts → http/body.d.ts} +27 -6
  41. package/dist/http/body.d.ts.map +1 -0
  42. package/dist/{body.js → http/body.js} +33 -13
  43. package/dist/http/body.js.map +1 -0
  44. package/dist/http/http.d.ts +42 -0
  45. package/dist/http/http.d.ts.map +1 -0
  46. package/dist/http/http.js +100 -0
  47. package/dist/http/http.js.map +1 -0
  48. package/dist/http/origins.d.ts +37 -0
  49. package/dist/http/origins.d.ts.map +1 -0
  50. package/dist/http/origins.js +87 -0
  51. package/dist/http/origins.js.map +1 -0
  52. package/dist/{dispatch.d.ts → mcp/dispatch.d.ts} +1 -1
  53. package/dist/mcp/dispatch.d.ts.map +1 -0
  54. package/dist/mcp/dispatch.js +99 -0
  55. package/dist/mcp/dispatch.js.map +1 -0
  56. package/dist/{jsonrpc.d.ts → mcp/jsonrpc.d.ts} +9 -0
  57. package/dist/mcp/jsonrpc.d.ts.map +1 -0
  58. package/dist/mcp/jsonrpc.js +88 -0
  59. package/dist/mcp/jsonrpc.js.map +1 -0
  60. package/dist/{methods.d.ts → mcp/methods.d.ts} +60 -11
  61. package/dist/mcp/methods.d.ts.map +1 -0
  62. package/dist/mcp/methods.js +84 -0
  63. package/dist/mcp/methods.js.map +1 -0
  64. package/dist/{protocol.d.ts → mcp/protocol.d.ts} +1 -3
  65. package/dist/mcp/protocol.d.ts.map +1 -0
  66. package/dist/{protocol.js → mcp/protocol.js} +1 -3
  67. package/dist/mcp/protocol.js.map +1 -0
  68. package/dist/mcp/registry.d.ts +58 -0
  69. package/dist/mcp/registry.d.ts.map +1 -0
  70. package/dist/mcp/registry.js +81 -0
  71. package/dist/mcp/registry.js.map +1 -0
  72. package/dist/mcp/rpc-handlers.d.ts +11 -0
  73. package/dist/mcp/rpc-handlers.d.ts.map +1 -0
  74. package/dist/mcp/rpc-handlers.js +133 -0
  75. package/dist/mcp/rpc-handlers.js.map +1 -0
  76. package/dist/{tools.d.ts → mcp/tools.d.ts} +20 -1
  77. package/dist/mcp/tools.d.ts.map +1 -0
  78. package/dist/mcp/tools.js +166 -0
  79. package/dist/mcp/tools.js.map +1 -0
  80. package/dist/{validate.d.ts → mcp/validate.d.ts} +18 -21
  81. package/dist/mcp/validate.d.ts.map +1 -0
  82. package/dist/{validate.js → mcp/validate.js} +59 -41
  83. package/dist/mcp/validate.js.map +1 -0
  84. package/dist/oauth/audit.d.ts +20 -0
  85. package/dist/oauth/audit.d.ts.map +1 -0
  86. package/dist/oauth/audit.js +29 -0
  87. package/dist/oauth/audit.js.map +1 -0
  88. package/dist/oauth/cimd/cimd-parse.d.ts +4 -0
  89. package/dist/oauth/cimd/cimd-parse.d.ts.map +1 -0
  90. package/dist/oauth/cimd/cimd-parse.js +70 -0
  91. package/dist/oauth/cimd/cimd-parse.js.map +1 -0
  92. package/dist/oauth/cimd/cimd-ssrf.d.ts +8 -0
  93. package/dist/oauth/cimd/cimd-ssrf.d.ts.map +1 -0
  94. package/dist/oauth/cimd/cimd-ssrf.js +193 -0
  95. package/dist/oauth/cimd/cimd-ssrf.js.map +1 -0
  96. package/dist/oauth/cimd/cimd.d.ts +36 -0
  97. package/dist/oauth/cimd/cimd.d.ts.map +1 -0
  98. package/dist/oauth/cimd/cimd.js +132 -0
  99. package/dist/oauth/cimd/cimd.js.map +1 -0
  100. package/dist/oauth/cimd/types.d.ts +12 -0
  101. package/dist/oauth/cimd/types.d.ts.map +1 -0
  102. package/dist/oauth/cimd/types.js +3 -0
  103. package/dist/oauth/cimd/types.js.map +1 -0
  104. package/dist/oauth/config.d.ts +51 -0
  105. package/dist/oauth/config.d.ts.map +1 -0
  106. package/dist/oauth/config.js +108 -0
  107. package/dist/oauth/config.js.map +1 -0
  108. package/dist/oauth/constants.d.ts +11 -0
  109. package/dist/oauth/constants.d.ts.map +1 -1
  110. package/dist/oauth/constants.js +11 -0
  111. package/dist/oauth/constants.js.map +1 -1
  112. package/dist/oauth/{base64url.d.ts → crypto/base64url.d.ts} +0 -1
  113. package/dist/oauth/crypto/base64url.d.ts.map +1 -0
  114. package/dist/oauth/{base64url.js → crypto/base64url.js} +0 -1
  115. package/dist/oauth/crypto/base64url.js.map +1 -0
  116. package/dist/oauth/crypto/clientauth.d.ts +13 -0
  117. package/dist/oauth/crypto/clientauth.d.ts.map +1 -0
  118. package/dist/oauth/crypto/clientauth.js +195 -0
  119. package/dist/oauth/crypto/clientauth.js.map +1 -0
  120. package/dist/oauth/crypto/codes.d.ts +65 -0
  121. package/dist/oauth/crypto/codes.d.ts.map +1 -0
  122. package/dist/oauth/crypto/codes.js +121 -0
  123. package/dist/oauth/crypto/codes.js.map +1 -0
  124. package/dist/oauth/crypto/hkdf.d.ts +13 -0
  125. package/dist/oauth/crypto/hkdf.d.ts.map +1 -0
  126. package/dist/oauth/crypto/hkdf.js +30 -0
  127. package/dist/oauth/crypto/hkdf.js.map +1 -0
  128. package/dist/oauth/crypto/keycache.d.ts +19 -0
  129. package/dist/oauth/crypto/keycache.d.ts.map +1 -0
  130. package/dist/oauth/crypto/keycache.js +44 -0
  131. package/dist/oauth/crypto/keycache.js.map +1 -0
  132. package/dist/oauth/crypto/pkce.d.ts.map +1 -0
  133. package/dist/oauth/{pkce.js → crypto/pkce.js} +1 -1
  134. package/dist/oauth/crypto/pkce.js.map +1 -0
  135. package/dist/oauth/{sealed.d.ts → crypto/sealed.d.ts} +12 -3
  136. package/dist/oauth/crypto/sealed.d.ts.map +1 -0
  137. package/dist/oauth/{sealed.js → crypto/sealed.js} +22 -14
  138. package/dist/oauth/crypto/sealed.js.map +1 -0
  139. package/dist/oauth/{secrethash.d.ts → crypto/secrethash.d.ts} +14 -0
  140. package/dist/oauth/crypto/secrethash.d.ts.map +1 -0
  141. package/dist/oauth/{secrethash.js → crypto/secrethash.js} +27 -11
  142. package/dist/oauth/crypto/secrethash.js.map +1 -0
  143. package/dist/oauth/deprecated.d.ts +52 -0
  144. package/dist/oauth/deprecated.d.ts.map +1 -0
  145. package/dist/oauth/deprecated.js +49 -0
  146. package/dist/oauth/deprecated.js.map +1 -0
  147. package/dist/oauth/endpoints/authorize.d.ts +3 -0
  148. package/dist/oauth/endpoints/authorize.d.ts.map +1 -0
  149. package/dist/oauth/endpoints/authorize.js +209 -0
  150. package/dist/oauth/endpoints/authorize.js.map +1 -0
  151. package/dist/oauth/endpoints/callback.d.ts +20 -0
  152. package/dist/oauth/endpoints/callback.d.ts.map +1 -0
  153. package/dist/oauth/endpoints/callback.js +31 -0
  154. package/dist/oauth/endpoints/callback.js.map +1 -0
  155. package/dist/oauth/endpoints/consent-page.d.ts +5 -0
  156. package/dist/oauth/endpoints/consent-page.d.ts.map +1 -0
  157. package/dist/oauth/endpoints/consent-page.js +63 -0
  158. package/dist/oauth/endpoints/consent-page.js.map +1 -0
  159. package/dist/oauth/endpoints/consent.d.ts +29 -0
  160. package/dist/oauth/endpoints/consent.d.ts.map +1 -0
  161. package/dist/oauth/endpoints/consent.js +98 -0
  162. package/dist/oauth/endpoints/consent.js.map +1 -0
  163. package/dist/oauth/{metadata.d.ts → endpoints/metadata.d.ts} +8 -2
  164. package/dist/oauth/endpoints/metadata.d.ts.map +1 -0
  165. package/dist/oauth/{metadata.js → endpoints/metadata.js} +10 -4
  166. package/dist/oauth/endpoints/metadata.js.map +1 -0
  167. package/dist/oauth/endpoints/register.d.ts +10 -0
  168. package/dist/oauth/endpoints/register.d.ts.map +1 -0
  169. package/dist/oauth/endpoints/register.js +96 -0
  170. package/dist/oauth/endpoints/register.js.map +1 -0
  171. package/dist/oauth/{revoke.d.ts → endpoints/revoke.d.ts} +1 -1
  172. package/dist/oauth/endpoints/revoke.d.ts.map +1 -0
  173. package/dist/oauth/{revoke.js → endpoints/revoke.js} +8 -18
  174. package/dist/oauth/endpoints/revoke.js.map +1 -0
  175. package/dist/oauth/endpoints/token.d.ts +3 -0
  176. package/dist/oauth/endpoints/token.d.ts.map +1 -0
  177. package/dist/oauth/{token.js → endpoints/token.js} +32 -25
  178. package/dist/oauth/endpoints/token.js.map +1 -0
  179. package/dist/oauth/{wellknown.d.ts → endpoints/wellknown.d.ts} +1 -1
  180. package/dist/oauth/endpoints/wellknown.d.ts.map +1 -0
  181. package/dist/oauth/{wellknown.js → endpoints/wellknown.js} +7 -9
  182. package/dist/oauth/endpoints/wellknown.js.map +1 -0
  183. package/dist/oauth/policy/redirect.d.ts.map +1 -0
  184. package/dist/oauth/policy/redirect.js.map +1 -0
  185. package/dist/oauth/policy/reqbody.d.ts +18 -0
  186. package/dist/oauth/policy/reqbody.d.ts.map +1 -0
  187. package/dist/oauth/policy/reqbody.js +68 -0
  188. package/dist/oauth/policy/reqbody.js.map +1 -0
  189. package/dist/oauth/{resource.d.ts → policy/resource.d.ts} +1 -1
  190. package/dist/oauth/policy/resource.d.ts.map +1 -0
  191. package/dist/oauth/{resource.js → policy/resource.js} +2 -2
  192. package/dist/oauth/policy/resource.js.map +1 -0
  193. package/dist/oauth/{scope.d.ts → policy/scope.d.ts} +2 -2
  194. package/dist/oauth/policy/scope.d.ts.map +1 -0
  195. package/dist/oauth/{scope.js → policy/scope.js} +3 -3
  196. package/dist/oauth/policy/scope.js.map +1 -0
  197. package/dist/oauth/router.d.ts +10 -13
  198. package/dist/oauth/router.d.ts.map +1 -1
  199. package/dist/oauth/router.js +93 -115
  200. package/dist/oauth/router.js.map +1 -1
  201. package/dist/oauth/types.d.ts +99 -45
  202. package/dist/oauth/types.d.ts.map +1 -1
  203. package/dist/oauth/types.js +1 -90
  204. package/dist/oauth/types.js.map +1 -1
  205. package/dist/server.d.ts +13 -12
  206. package/dist/server.d.ts.map +1 -1
  207. package/dist/server.js +10 -8
  208. package/dist/server.js.map +1 -1
  209. package/dist/util/defined.d.ts +11 -0
  210. package/dist/util/defined.d.ts.map +1 -0
  211. package/dist/util/defined.js +15 -0
  212. package/dist/util/defined.js.map +1 -0
  213. package/dist/util/json.d.ts +3 -0
  214. package/dist/util/json.d.ts.map +1 -0
  215. package/dist/util/json.js +3 -0
  216. package/dist/util/json.js.map +1 -0
  217. package/docs/ROADMAP.md +37 -47
  218. package/docs/compatibility.md +86 -0
  219. package/docs/diagrams/demo-tool-result.png +0 -0
  220. package/docs/diagrams/mcp-trellis-architecture.html +305 -0
  221. package/docs/guide.md +46 -16
  222. package/docs/reference.md +55 -22
  223. package/docs/security.md +58 -9
  224. package/docs/troubleshooting.md +19 -0
  225. package/package.json +27 -10
  226. package/dist/adapters/origins.d.ts +0 -19
  227. package/dist/adapters/origins.d.ts.map +0 -1
  228. package/dist/adapters/origins.js +0 -52
  229. package/dist/adapters/origins.js.map +0 -1
  230. package/dist/body.d.ts.map +0 -1
  231. package/dist/body.js.map +0 -1
  232. package/dist/dispatch.d.ts.map +0 -1
  233. package/dist/dispatch.js +0 -119
  234. package/dist/dispatch.js.map +0 -1
  235. package/dist/http.d.ts +0 -17
  236. package/dist/http.d.ts.map +0 -1
  237. package/dist/http.js +0 -38
  238. package/dist/http.js.map +0 -1
  239. package/dist/jsonrpc.d.ts.map +0 -1
  240. package/dist/jsonrpc.js +0 -18
  241. package/dist/jsonrpc.js.map +0 -1
  242. package/dist/methods.d.ts.map +0 -1
  243. package/dist/methods.js +0 -130
  244. package/dist/methods.js.map +0 -1
  245. package/dist/oauth/authorize.d.ts +0 -3
  246. package/dist/oauth/authorize.d.ts.map +0 -1
  247. package/dist/oauth/authorize.js +0 -141
  248. package/dist/oauth/authorize.js.map +0 -1
  249. package/dist/oauth/base64url.d.ts.map +0 -1
  250. package/dist/oauth/base64url.js.map +0 -1
  251. package/dist/oauth/clientauth.d.ts +0 -24
  252. package/dist/oauth/clientauth.d.ts.map +0 -1
  253. package/dist/oauth/clientauth.js +0 -119
  254. package/dist/oauth/clientauth.js.map +0 -1
  255. package/dist/oauth/codes.d.ts +0 -30
  256. package/dist/oauth/codes.d.ts.map +0 -1
  257. package/dist/oauth/codes.js +0 -85
  258. package/dist/oauth/codes.js.map +0 -1
  259. package/dist/oauth/consent.d.ts +0 -65
  260. package/dist/oauth/consent.d.ts.map +0 -1
  261. package/dist/oauth/consent.js +0 -173
  262. package/dist/oauth/consent.js.map +0 -1
  263. package/dist/oauth/metadata.d.ts.map +0 -1
  264. package/dist/oauth/metadata.js.map +0 -1
  265. package/dist/oauth/pkce.d.ts.map +0 -1
  266. package/dist/oauth/pkce.js.map +0 -1
  267. package/dist/oauth/redirect.d.ts.map +0 -1
  268. package/dist/oauth/redirect.js.map +0 -1
  269. package/dist/oauth/reqbody.d.ts +0 -10
  270. package/dist/oauth/reqbody.d.ts.map +0 -1
  271. package/dist/oauth/reqbody.js +0 -29
  272. package/dist/oauth/reqbody.js.map +0 -1
  273. package/dist/oauth/resource.d.ts.map +0 -1
  274. package/dist/oauth/resource.js.map +0 -1
  275. package/dist/oauth/revoke.d.ts.map +0 -1
  276. package/dist/oauth/revoke.js.map +0 -1
  277. package/dist/oauth/scope.d.ts.map +0 -1
  278. package/dist/oauth/scope.js.map +0 -1
  279. package/dist/oauth/sealed.d.ts.map +0 -1
  280. package/dist/oauth/sealed.js.map +0 -1
  281. package/dist/oauth/secrethash.d.ts.map +0 -1
  282. package/dist/oauth/secrethash.js.map +0 -1
  283. package/dist/oauth/token.d.ts +0 -3
  284. package/dist/oauth/token.d.ts.map +0 -1
  285. package/dist/oauth/token.js.map +0 -1
  286. package/dist/oauth/wellknown.d.ts.map +0 -1
  287. package/dist/oauth/wellknown.js.map +0 -1
  288. package/dist/protocol.d.ts.map +0 -1
  289. package/dist/protocol.js.map +0 -1
  290. package/dist/registry.d.ts +0 -37
  291. package/dist/registry.d.ts.map +0 -1
  292. package/dist/registry.js +0 -77
  293. package/dist/registry.js.map +0 -1
  294. package/dist/tools.d.ts.map +0 -1
  295. package/dist/tools.js +0 -98
  296. package/dist/tools.js.map +0 -1
  297. package/dist/validate.d.ts.map +0 -1
  298. package/dist/validate.js.map +0 -1
  299. /package/dist/oauth/{pkce.d.ts → crypto/pkce.d.ts} +0 -0
  300. /package/dist/oauth/{redirect.d.ts → policy/redirect.d.ts} +0 -0
  301. /package/dist/oauth/{redirect.js → policy/redirect.js} +0 -0
package/dist/server.d.ts CHANGED
@@ -1,16 +1,17 @@
1
- export { createMcpApp, type McpApp, type McpAppAuth, type McpAppOptions, type VerifiedToken, } from "./app.js";
1
+ export { createMcpApp, type McpApp, type McpAppAuth, type McpAppOptions, type UnifiedAuditEntry, type VerifiedToken, } from "./app.js";
2
2
  export { consoleAudit } from "./audit.js";
3
- export { matchesAny, parseBearer, rejectQueryToken, timingSafeEqual, type WwwAuthenticateOptions, wwwAuthenticateHeader, } from "./auth/bearer.js";
3
+ export { parseBearer, rejectQueryToken, type WwwAuthenticateOptions, wwwAuthenticateHeader, } from "./auth/bearer.js";
4
+ export { type SignedTokenAuthOptions, signedTokenAuth, } from "./auth/signed-token.js";
4
5
  export { authMethodsFor, CLIENT_PROFILES, type ClientName, type ClientProfile, DEFAULT_CLIENTS, hasDynamicClient, preRegisteredClients, redirectUrisFor, } from "./clients.js";
5
- export { type AuditEntry, createMcpHandler, type McpHandler, type McpHandlerOptions, type McpPorts, type Principal, type ServerInfo, } from "./dispatch.js";
6
- export { corsHeaders, emptyResponse, jsonResponse, methodNotAllowed, optionsResponse, } from "./http.js";
7
- export { JSONRPC_INTERNAL_ERROR, JSONRPC_INVALID_PARAMS, JSONRPC_INVALID_REQUEST, JSONRPC_METHOD_NOT_FOUND, JSONRPC_PARSE_ERROR, JSONRPC_UNAUTHORIZED, type JsonRpcId, type JsonRpcRequest, type JsonRpcResponse, rpcError, rpcResult, } from "./jsonrpc.js";
8
- export type { CodeStore } from "./oauth/codes.js";
9
- export type { ConsentOptions, ConsentRequest } from "./oauth/consent.js";
6
+ export * from "./deprecated.js";
7
+ export { type JsonResponseInput, type JsonResponseOptions, jsonResponse, } from "./http/http.js";
8
+ export { type AuditEntry, createMcpHandler, type McpHandler, type McpHandlerOptions, type McpPorts, type Principal, type ServerInfo, } from "./mcp/dispatch.js";
9
+ export { JSONRPC_INTERNAL_ERROR, JSONRPC_INVALID_PARAMS, JSONRPC_INVALID_REQUEST, JSONRPC_METHOD_NOT_FOUND, JSONRPC_PARSE_ERROR, JSONRPC_UNAUTHORIZED, type JsonRpcId, type JsonRpcRequest, type JsonRpcResponse, rpcError, rpcResult, } from "./mcp/jsonrpc.js";
10
+ export { DEFAULT_PROTOCOL_VERSION, PROTOCOL_VERSIONS } from "./mcp/protocol.js";
11
+ export { createToolRegistry, type RegistryOptions, type ToolDef, type ToolHandler, type ToolListEntry, type ToolRegistry, type ToolResult, } from "./mcp/registry.js";
12
+ export { type ApiRequest, type ApiToolOptions, apiTool, type DefineToolOptions, defineTool, type StandardSchemaV1, } from "./mcp/tools.js";
13
+ export type { JsonSchema } from "./mcp/validate.js";
14
+ export type { CodeStore } from "./oauth/crypto/codes.js";
10
15
  /** Auth-port types used by `McpAppAuth` — annotate extracted stores/callbacks. */
11
- export type { ClientStore, MintAccessTokenInput, MintedToken, OAuthUser, RefreshAccessTokenInput, RegisteredClient, RevokeTokenInput, } from "./oauth/types.js";
12
- export { ASSUMED_HEADER_PROTOCOL_VERSION, DEFAULT_PROTOCOL_VERSION, PROTOCOL_VERSIONS, pickProtocolVersion, } from "./protocol.js";
13
- export { createToolRegistry, type RegistryOptions, type ToolDef, type ToolHandler, type ToolListEntry, type ToolRegistry, type ToolResult, } from "./registry.js";
14
- export { type ApiRequest, type ApiToolOptions, apiTool, type DefineToolOptions, defineTool, type StandardSchemaV1, } from "./tools.js";
15
- export { IGNORED_SCHEMA_KEYWORDS, JSON_SCHEMA_TYPES, type JsonSchema, missingObjectType, SUPPORTED_SCHEMA_KEYWORDS, unsupportedKeywords, validateAgainstSchema, } from "./validate.js";
16
+ export type { ClientStore, ConsentOptions, ConsentRequest, MintAccessTokenInput, MintedToken, OAuthUser, RefreshAccessTokenInput, RegisteredClient, RevokeTokenInput, } from "./oauth/types.js";
16
17
  //# sourceMappingURL=server.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EACZ,KAAK,MAAM,EACX,KAAK,UAAU,EACf,KAAK,aAAa,EAClB,KAAK,aAAa,GACnB,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EACL,UAAU,EACV,WAAW,EACX,gBAAgB,EAChB,eAAe,EACf,KAAK,sBAAsB,EAC3B,qBAAqB,GACtB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACL,cAAc,EACd,eAAe,EACf,KAAK,UAAU,EACf,KAAK,aAAa,EAClB,eAAe,EACf,gBAAgB,EAChB,oBAAoB,EACpB,eAAe,GAChB,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,KAAK,UAAU,EACf,gBAAgB,EAChB,KAAK,UAAU,EACf,KAAK,iBAAiB,EACtB,KAAK,QAAQ,EACb,KAAK,SAAS,EACd,KAAK,UAAU,GAChB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,WAAW,EACX,aAAa,EACb,YAAY,EACZ,gBAAgB,EAChB,eAAe,GAChB,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,sBAAsB,EACtB,sBAAsB,EACtB,uBAAuB,EACvB,wBAAwB,EACxB,mBAAmB,EACnB,oBAAoB,EACpB,KAAK,SAAS,EACd,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,QAAQ,EACR,SAAS,GACV,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAClD,YAAY,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzE,kFAAkF;AAClF,YAAY,EACV,WAAW,EACX,oBAAoB,EACpB,WAAW,EACX,SAAS,EACT,uBAAuB,EACvB,gBAAgB,EAChB,gBAAgB,GACjB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACL,+BAA+B,EAC/B,wBAAwB,EACxB,iBAAiB,EACjB,mBAAmB,GACpB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,kBAAkB,EAClB,KAAK,eAAe,EACpB,KAAK,OAAO,EACZ,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,UAAU,GAChB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,KAAK,UAAU,EACf,KAAK,cAAc,EACnB,OAAO,EACP,KAAK,iBAAiB,EACtB,UAAU,EACV,KAAK,gBAAgB,GACtB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,uBAAuB,EACvB,iBAAiB,EACjB,KAAK,UAAU,EACf,iBAAiB,EACjB,yBAAyB,EACzB,mBAAmB,EACnB,qBAAqB,GACtB,MAAM,eAAe,CAAC"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EACZ,KAAK,MAAM,EACX,KAAK,UAAU,EACf,KAAK,aAAa,EAClB,KAAK,iBAAiB,EACtB,KAAK,aAAa,GACnB,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EACL,WAAW,EACX,gBAAgB,EAChB,KAAK,sBAAsB,EAC3B,qBAAqB,GACtB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,KAAK,sBAAsB,EAC3B,eAAe,GAChB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EACL,cAAc,EACd,eAAe,EACf,KAAK,UAAU,EACf,KAAK,aAAa,EAClB,eAAe,EACf,gBAAgB,EAChB,oBAAoB,EACpB,eAAe,GAChB,MAAM,cAAc,CAAC;AAEtB,cAAc,iBAAiB,CAAC;AAChC,OAAO,EACL,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EACxB,YAAY,GACb,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,KAAK,UAAU,EACf,gBAAgB,EAChB,KAAK,UAAU,EACf,KAAK,iBAAiB,EACtB,KAAK,QAAQ,EACb,KAAK,SAAS,EACd,KAAK,UAAU,GAChB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,sBAAsB,EACtB,sBAAsB,EACtB,uBAAuB,EACvB,wBAAwB,EACxB,mBAAmB,EACnB,oBAAoB,EACpB,KAAK,SAAS,EACd,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,QAAQ,EACR,SAAS,GACV,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,wBAAwB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAChF,OAAO,EACL,kBAAkB,EAClB,KAAK,eAAe,EACpB,KAAK,OAAO,EACZ,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,UAAU,GAChB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,KAAK,UAAU,EACf,KAAK,cAAc,EACnB,OAAO,EACP,KAAK,iBAAiB,EACtB,UAAU,EACV,KAAK,gBAAgB,GACtB,MAAM,gBAAgB,CAAC;AACxB,YAAY,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpD,YAAY,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACzD,kFAAkF;AAClF,YAAY,EACV,WAAW,EACX,cAAc,EACd,cAAc,EACd,oBAAoB,EACpB,WAAW,EACX,SAAS,EACT,uBAAuB,EACvB,gBAAgB,EAChB,gBAAgB,GACjB,MAAM,kBAAkB,CAAC"}
package/dist/server.js CHANGED
@@ -1,12 +1,14 @@
1
1
  export { createMcpApp, } from "./app.js";
2
2
  export { consoleAudit } from "./audit.js";
3
- export { matchesAny, parseBearer, rejectQueryToken, timingSafeEqual, wwwAuthenticateHeader, } from "./auth/bearer.js";
3
+ export { parseBearer, rejectQueryToken, wwwAuthenticateHeader, } from "./auth/bearer.js";
4
+ export { signedTokenAuth, } from "./auth/signed-token.js";
4
5
  export { authMethodsFor, CLIENT_PROFILES, DEFAULT_CLIENTS, hasDynamicClient, preRegisteredClients, redirectUrisFor, } from "./clients.js";
5
- export { createMcpHandler, } from "./dispatch.js";
6
- export { corsHeaders, emptyResponse, jsonResponse, methodNotAllowed, optionsResponse, } from "./http.js";
7
- export { JSONRPC_INTERNAL_ERROR, JSONRPC_INVALID_PARAMS, JSONRPC_INVALID_REQUEST, JSONRPC_METHOD_NOT_FOUND, JSONRPC_PARSE_ERROR, JSONRPC_UNAUTHORIZED, rpcError, rpcResult, } from "./jsonrpc.js";
8
- export { ASSUMED_HEADER_PROTOCOL_VERSION, DEFAULT_PROTOCOL_VERSION, PROTOCOL_VERSIONS, pickProtocolVersion, } from "./protocol.js";
9
- export { createToolRegistry, } from "./registry.js";
10
- export { apiTool, defineTool, } from "./tools.js";
11
- export { IGNORED_SCHEMA_KEYWORDS, JSON_SCHEMA_TYPES, missingObjectType, SUPPORTED_SCHEMA_KEYWORDS, unsupportedKeywords, validateAgainstSchema, } from "./validate.js";
6
+ // Moved to `mcp-trellis/advanced`; deprecated aliases until 3.0.
7
+ export * from "./deprecated.js";
8
+ export { jsonResponse, } from "./http/http.js";
9
+ export { createMcpHandler, } from "./mcp/dispatch.js";
10
+ export { JSONRPC_INTERNAL_ERROR, JSONRPC_INVALID_PARAMS, JSONRPC_INVALID_REQUEST, JSONRPC_METHOD_NOT_FOUND, JSONRPC_PARSE_ERROR, JSONRPC_UNAUTHORIZED, rpcError, rpcResult, } from "./mcp/jsonrpc.js";
11
+ export { DEFAULT_PROTOCOL_VERSION, PROTOCOL_VERSIONS } from "./mcp/protocol.js";
12
+ export { createToolRegistry, } from "./mcp/registry.js";
13
+ export { apiTool, defineTool, } from "./mcp/tools.js";
12
14
  //# sourceMappingURL=server.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,GAKb,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EACL,UAAU,EACV,WAAW,EACX,gBAAgB,EAChB,eAAe,EAEf,qBAAqB,GACtB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACL,cAAc,EACd,eAAe,EAGf,eAAe,EACf,gBAAgB,EAChB,oBAAoB,EACpB,eAAe,GAChB,MAAM,cAAc,CAAC;AAEtB,OAAO,EAEL,gBAAgB,GAMjB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,WAAW,EACX,aAAa,EACb,YAAY,EACZ,gBAAgB,EAChB,eAAe,GAChB,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,sBAAsB,EACtB,sBAAsB,EACtB,uBAAuB,EACvB,wBAAwB,EACxB,mBAAmB,EACnB,oBAAoB,EAIpB,QAAQ,EACR,SAAS,GACV,MAAM,cAAc,CAAC;AActB,OAAO,EACL,+BAA+B,EAC/B,wBAAwB,EACxB,iBAAiB,EACjB,mBAAmB,GACpB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,kBAAkB,GAOnB,MAAM,eAAe,CAAC;AACvB,OAAO,EAGL,OAAO,EAEP,UAAU,GAEX,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,uBAAuB,EACvB,iBAAiB,EAEjB,iBAAiB,EACjB,yBAAyB,EACzB,mBAAmB,EACnB,qBAAqB,GACtB,MAAM,eAAe,CAAC"}
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,GAMb,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EACL,WAAW,EACX,gBAAgB,EAEhB,qBAAqB,GACtB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAEL,eAAe,GAChB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EACL,cAAc,EACd,eAAe,EAGf,eAAe,EACf,gBAAgB,EAChB,oBAAoB,EACpB,eAAe,GAChB,MAAM,cAAc,CAAC;AACtB,iEAAiE;AACjE,cAAc,iBAAiB,CAAC;AAChC,OAAO,EAGL,YAAY,GACb,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAEL,gBAAgB,GAMjB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,sBAAsB,EACtB,sBAAsB,EACtB,uBAAuB,EACvB,wBAAwB,EACxB,mBAAmB,EACnB,oBAAoB,EAIpB,QAAQ,EACR,SAAS,GACV,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,wBAAwB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAChF,OAAO,EACL,kBAAkB,GAOnB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAGL,OAAO,EAEP,UAAU,GAEX,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,11 @@
1
+ /** `keys` of `T` with `undefined` removed from each value type, all optional. */
2
+ export type DefinedProps<T, K extends keyof T> = {
3
+ [P in K]?: Exclude<T[P], undefined>;
4
+ };
5
+ /**
6
+ * Copies only the listed keys whose value is not `undefined`. Under
7
+ * `exactOptionalPropertyTypes` an explicit `undefined` is not assignable to
8
+ * an optional property, so forwarding optional options needs exactly this.
9
+ */
10
+ export declare const pickDefined: <T extends object, K extends keyof T>(source: T, keys: readonly K[]) => DefinedProps<T, K>;
11
+ //# sourceMappingURL=defined.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"defined.d.ts","sourceRoot":"","sources":["../../src/util/defined.ts"],"names":[],"mappings":"AAAA,iFAAiF;AACjF,MAAM,MAAM,YAAY,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,CAAC,IAAI;KAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC;CAAE,CAAC;AAEzF;;;;GAIG;AACH,eAAO,MAAM,WAAW,GAAI,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,MAAM,CAAC,EAC7D,QAAQ,CAAC,EACT,MAAM,SAAS,CAAC,EAAE,KACjB,YAAY,CAAC,CAAC,EAAE,CAAC,CAOnB,CAAC"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Copies only the listed keys whose value is not `undefined`. Under
3
+ * `exactOptionalPropertyTypes` an explicit `undefined` is not assignable to
4
+ * an optional property, so forwarding optional options needs exactly this.
5
+ */
6
+ export const pickDefined = (source, keys) => {
7
+ const picked = {};
8
+ for (const key of keys) {
9
+ const value = source[key];
10
+ if (value !== undefined)
11
+ picked[key] = value;
12
+ }
13
+ return picked;
14
+ };
15
+ //# sourceMappingURL=defined.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"defined.js","sourceRoot":"","sources":["../../src/util/defined.ts"],"names":[],"mappings":"AAGA;;;;GAIG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,CACzB,MAAS,EACT,IAAkB,EACE,EAAE;IACtB,MAAM,MAAM,GAAuB,EAAE,CAAC;IACtC,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;QAC1B,IAAI,KAAK,KAAK,SAAS;YAAE,MAAM,CAAC,GAAG,CAAC,GAAG,KAAiC,CAAC;IAC3E,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ /** A parsed JSON object — not `null`, not an array. */
2
+ export declare const isJsonObject: (value: unknown) => value is Record<string, unknown>;
3
+ //# sourceMappingURL=json.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json.d.ts","sourceRoot":"","sources":["../../src/util/json.ts"],"names":[],"mappings":"AAAA,uDAAuD;AACvD,eAAO,MAAM,YAAY,GAAI,OAAO,OAAO,KAAG,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CACP,CAAC"}
@@ -0,0 +1,3 @@
1
+ /** A parsed JSON object — not `null`, not an array. */
2
+ export const isJsonObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
3
+ //# sourceMappingURL=json.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json.js","sourceRoot":"","sources":["../../src/util/json.ts"],"names":[],"mappings":"AAAA,uDAAuD;AACvD,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,KAAc,EAAoC,EAAE,CAC/E,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC"}
package/docs/ROADMAP.md CHANGED
@@ -1,24 +1,33 @@
1
1
  # mcp-trellis — roadmap
2
2
 
3
- Status: 2026-08-21. Written against MCP spec revision `2026-07-28`.
3
+ Status: 2026-09-14. Written against MCP spec revision `2026-07-28`.
4
4
 
5
5
  ## What this library is
6
6
 
7
- > **The easy way to build a secure MCP server that works with Claude, Gemini,
8
- > and Codex** — on any Web-standard runtime, with no database and no vendor.
7
+ > **Existing SaaS → authenticated AI connector SDK** — MCP + self-hosted OAuth
8
+ > AS in one npm install, on any Web-standard runtime, with no database and no
9
+ > vendor.
9
10
 
10
11
  The differentiating axis is **clients**, not runtimes. Runtime portability is
11
12
  table stakes; the official SDK has it too. What nobody in TypeScript ships is
12
13
  both halves — the MCP handler *and* a self-hosted OAuth authorization server —
13
14
  in one package you can drop into a Next.js route or a Deno server.
14
15
 
15
- | | Portable runtime | Self-hosted | AS included | Zero-dep |
16
+ Contrast composition stacks that split the MCP runtime from the identity
17
+ product (e.g. xmcp + Scalekit): those are 2–3 products to wire; mcp-trellis is
18
+ one package with BYO-auth ports.
19
+
20
+ | | Portable runtime | Self-hosted AS | One npm install | Zero-dep |
16
21
  |---|---|---|---|---|
17
- | Official SDK v2 | yes | yes | **no** | no |
22
+ | Official SDK v2 | yes | **no** | yes (handler only) | no |
18
23
  | `workers-oauth-provider` | Workers only | yes | yes | — |
19
- | Auth0 / Authlete / Clerk / WorkOS | yes | **no** (SaaS) | yes | — |
24
+ | Auth0 / Authlete / Clerk | yes | **no** (SaaS) | no (IdP + MCP) | — |
20
25
  | Better Auth | yes | yes | yes, but full stack + DB | no |
21
- | **mcp-trellis** | yes | yes | yes | yes |
26
+ | **xmcp** | yes | **no** (compose) | no — pair with IdP | — |
27
+ | **Scalekit** | yes | managed connector IdP | no — pair with MCP runtime | — |
28
+ | **WorkOS Standalone Connect** | yes | managed | no — IdP + your MCP | — |
29
+ | **Descope** | yes | managed | no — IdP + your MCP | — |
30
+ | **mcp-trellis** | yes | yes | **yes** (handler + AS) | yes |
22
31
 
23
32
  The official SDK explicitly does not provide an authorization server — it offers
24
33
  SDK-level opt-ins and expects you to bring the infrastructure. That gap is the
@@ -110,7 +119,9 @@ a proper JSON-RPC error.
110
119
  - **Claims on `Principal`.** Optional `claims` from `verifyToken` /
111
120
  `VerifiedToken` flow into `context` (plan/role metadata — not the
112
121
  Host→tenant isolation key). Host-origin allowlisting (`allowedOrigins` on
113
- `asNodeHandler`) is **required** when origin is Host-derived.
122
+ `asNodeHandler`) is **required** when origin is Host-derived. Separately,
123
+ browser `Origin` on MCP is gated by `allowedRequestOrigins` (fail-closed
124
+ when the header is present; native clients omit it).
114
125
 
115
126
  - **`validateArgs` fail-fast.** With `validateArgs: true`, unsupported JSON
116
127
  Schema keywords throw at `createToolRegistry` construction instead of
@@ -210,49 +221,28 @@ a proper JSON-RPC error.
210
221
  MCP audit hook. Sees the real reason behind a collapsed `invalid_client`
211
222
  or a rejected `codeSecret`, which the caller never does.
212
223
 
224
+ **2.0 — CIMD, unified audit, recipes.**
225
+
226
+ - **CIMD (Client ID Metadata Documents)** — opt-in (`cimd: true`). HTTPS URL
227
+ `client_id`s are fetched and validated with SSRF hardening (public hosts
228
+ only, size / redirect / timeout caps). Advertises
229
+ `client_id_metadata_document_supported`. Optional `cimdCache` port.
230
+ Off by default until connect-pinned fetch closes the DNS-rebinding ceiling.
231
+ - **Unified `audit` sink** on `createMcpApp` — one callback for MCP and
232
+ OAuth events (`source: "mcp" | "oauth"`); `auth.audit` remains an
233
+ OAuth-only override.
234
+ - **Framework recipes** — `examples/nextjs-saas/`, `examples/express.ts`.
235
+ - **Reference MCP Registry server** — `examples/project-desk/`
236
+ (`io.github.amir1824/project-desk`, remotes only; not the SDK package).
237
+ - Fail-closed defaults: `allowInMemoryCodeStore` / `validateArgs`.
238
+ - **RFC 9207 `iss`** on authorize / error redirects; AS metadata advertises
239
+ `authorization_response_iss_parameter_supported`.
240
+
213
241
  ---
214
242
 
215
243
  ## Next
216
244
 
217
- ### 1. CIMD — Client ID Metadata Documents
218
-
219
- DCR is deprecated as of `2026-07-28`; CIMD is the recommended replacement and
220
- the direction Claude and Codex are heading. The client publishes JSON at an
221
- HTTPS URL and uses that URL as its `client_id`; the AS resolves it on demand.
222
-
223
- AS-side requirements: detect URL-formatted `client_id`; fetch it; **MUST**
224
- validate the document's `client_id` equals the URL exactly; **MUST** validate
225
- the request's `redirect_uri` against the document's `redirect_uris`; **SHOULD**
226
- cache respecting HTTP cache headers; advertise
227
- `client_id_metadata_document_supported: true`.
228
-
229
- This slots cleanly into the existing shape — pure `fetch` plus validation, with
230
- caching as a port. It also completes the picture: the spec defines exactly three
231
- registration mechanisms, and they map one-to-one onto the three clients.
232
-
233
- ```
234
- CIMD → Claude, Codex (public + PKCE)
235
- pre-registration → Gemini Enterprise (confidential) ← shipped
236
- DCR → legacy fallback ← shipped
237
- ```
238
-
239
- The security work is the real work: an AS that fetches attacker-supplied URLs is
240
- an SSRF engine unless it blocks private/loopback/link-local ranges and DNS
241
- rebinding, caps redirects, response size, and timeout, and refuses non-HTTPS.
242
- Cloudflare's implementation is a useful reference for what "done right" means
243
- (5 KB cap, 10 s timeout, public clients only).
244
-
245
- Note: CIMD is not unclaimed. Authlete, Auth0, Clerk, and `workers-oauth-provider`
246
- all ship it. The claim here is narrower and still true — none of them is a
247
- portable, self-hosted, zero-dependency library.
248
-
249
- ### 2. RFC 9207 — `iss` in the authorization response
250
-
251
- Add `iss` to the authorize redirect and
252
- `authorization_response_iss_parameter_supported` to AS metadata. Small, and a
253
- spec-level SHOULD.
254
-
255
- ### 3. Protocol currency — `2026-07-28`
245
+ ### 1. Protocol currency — `2026-07-28`
256
246
 
257
247
  Deferred deliberately: Claude, Gemini, and Codex all work against current
258
248
  revisions today, and the official SDK already covers dual-era for anyone who
@@ -0,0 +1,86 @@
1
+ # Compatibility evidence
2
+
3
+ Updated 2026-09-14. Repository implementation and automated coverage are in good
4
+ shape after the pre-prod security pass. **Vendor-client UI sessions are still
5
+ Pending** — do not convert product rows to ✅ until a live Claude/ChatGPT/Codex/Gemini
6
+ check below is filled in.
7
+
8
+ | Product | Server profile | Repository evidence | Live evidence |
9
+ |---|---|---|---|
10
+ | Claude custom connector | `claude`: DCR / CIMD, public client, S256 PKCE; built-in callback | `test/oauth/policy/clients.test.ts`, `test/oauth/endpoints/dcr.test.ts`, `test/oauth/cimd/cimd.test.ts`, `test/oauth/crypto/pkce.test.ts`; saas-demo e2e + `scripts/prep-claude-oauth.mjs` | Pending (UI) |
11
+ | ChatGPT | `codex`: public-client profile; exact hosted callback must be configured | Profile tests only; no ChatGPT UI test | Pending |
12
+ | Codex | `codex`: public client, PKCE, loopback callbacks allowed | Profile/redirect tests; no actual Codex login run | Pending |
13
+ | Gemini Enterprise | `gemini`: `clientStore`, pre-registration, `client_secret_basic` / `client_secret_post` | Client authentication tests; no Enterprise environment | Pending |
14
+
15
+ The Gemini profile does not imply compatibility with Gemini CLI or every Gemini product. ChatGPT and Codex need separate live checks even though the package groups them under one profile.
16
+
17
+ `src/mcp/protocol.ts` implements `2024-11-05`, `2025-03-26`, `2025-06-18`. Initialization defaults to `2025-06-18`; absent request headers use `2025-03-26`. This is an implementation inventory, not a claim to implement the latest revision. **CIMD is shipped opt-in** (`cimd: true` on `createMcpApp` / `createOAuthRouter`; off by default — see [security.md](security.md) SSRF ceiling). Live vendor UI evidence stays **Pending** until an operator connects a real client.
18
+
19
+ ## Demo deploy (Worker)
20
+
21
+ **Project desk** (Registry remotes target): [`examples/project-desk/worker.ts`](../examples/project-desk/worker.ts)
22
+ via root [`wrangler.toml`](../wrangler.toml).
23
+
24
+ ```bash
25
+ npx wrangler secret put DEMO_PASSWORD # project-desk-demo for the public demo
26
+ npx wrangler secret put OAUTH_CODE_SECRET
27
+ npx wrangler deploy
28
+ ```
29
+
30
+ MCP URL: `https://mcp-trellis-project-desk.<workers-subdomain>.workers.dev/mcp`.
31
+ Operator checklist: [`examples/project-desk/PUBLISH.md`](../examples/project-desk/PUBLISH.md).
32
+ This does **not** replace the live client rows below.
33
+
34
+ Minimal ping-only Worker recipe (not the hosted demo):
35
+ [`examples/cloudflare-worker.ts`](../examples/cloudflare-worker.ts).
36
+
37
+ ## Host contract covered in-repo
38
+
39
+ `examples/project-desk` mints refresh tokens and enforces RFC 6749 §6: requested
40
+ refresh `scope` must be ⊆ the scopes originally bound to that refresh token
41
+ (`isScopeSubset` pattern also in `examples/stores.ts`). Escalation →
42
+ `invalid_grant`. Covered by `test/e2e/saas-demo.test.ts`.
43
+
44
+ ## Automated package smoke (not a vendor live pass)
45
+
46
+ ```bash
47
+ npm run smoke:pack
48
+ ```
49
+
50
+ Installs the local `npm pack` tarball in a temp directory and imports
51
+ `createMcpApp` / `asNodeHandler`. Record date/commit when you run it before a
52
+ release; it does **not** replace the live client row.
53
+
54
+ | Date | Commit / package | Command | Result |
55
+ |---|---|---|---|
56
+ | 2026-09-12 | unreleased working tree (`1.1.0` pack) | `npm run smoke:pack` | Pass — `createMcpApp` + `asNodeHandler` import from tarball |
57
+
58
+ ## Evidence required for a live pass
59
+
60
+ Record client product, version/build (or web UI and test date), account tier, package version/commit, hosting environment and configured callback. Capture discovery → registration → app login → consent → token exchange → initialize → tools/list → `list_my_projects`. Verify wrong audience/invalid token rejection and user isolation separately. Save sanitized output or recording; exclude cookies, passwords, codes and tokens.
61
+
62
+ Against a public HTTPS demo (`PUBLIC_ORIGIN` + `DEMO_PASSWORD=project-desk-demo`):
63
+
64
+ ```bash
65
+ npm run demo # reverse-proxy to HTTPS; set PUBLIC_ORIGIN
66
+ # or use the deployed Worker from examples/project-desk/PUBLISH.md
67
+ node scripts/prep-claude-oauth.mjs # scripted OAuth + refresh scope + tool
68
+ # Then open the vendor UI with MCP URL https://YOUR-HOST/mcp and record below.
69
+ ```
70
+
71
+ | Date | Client/build | Package/commit | Protocol negotiated | Tool + expected result | Evidence | Result |
72
+ |---|---|---|---|---|---|---|
73
+ | — | — | — | — | — | — | Pending |
74
+
75
+ ## Under-ten-minute onboarding test
76
+
77
+ Use a clean folder and the published npm tarball, start a timer at `npm install`, and stop at a real client's first correct user-scoped tool response. Record setup prerequisites, elapsed time, every edit and any error. A local source import or simulated OAuth flow is insufficient. Target: under ten minutes with hosting and a supported client account available; no time claim is published until measured.
78
+
79
+ | Field | Value |
80
+ |---|---|
81
+ | Start (`npm install`) | — |
82
+ | Stop (first correct tool in real client) | — |
83
+ | Elapsed | — |
84
+ | Prerequisites (hosting, account, callback) | — |
85
+ | Edits / errors | — |
86
+ | Result | Pending |