Skip to content

Commit cb400a3

Browse files
authored
Merge pull request #11 from codelitdev/mcp-july-26-update
MCP server updated to July 26 spec
2 parents d4970fd + e694dd3 commit cb400a3

45 files changed

Lines changed: 9352 additions & 445 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

apps/api/README.md

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -292,8 +292,11 @@ Summary of what's implemented:
292292

293293
## MCP Server
294294

295-
The MCP server is exposed at `POST /mcp` over JSON-RPC HTTP. Use the
296-
`Mcp-Session-Id` header for session continuation.
295+
The MCP server is exposed at `POST /mcp` using the TypeScript SDK 2's stateless
296+
Streamable HTTP handler. Clients using the `2026-07-28` protocol use the modern
297+
request pattern, while 2025-era Streamable HTTP clients use the SDK's stateless
298+
`initialize` compatibility path. Neither path creates or retains session IDs,
299+
and the legacy HTTP+SSE transport is not supported.
297300

298301
MCP clients authenticate the same way as REST clients:
299302

@@ -306,8 +309,14 @@ OAuth-capable MCP clients can discover metadata from:
306309
- `GET /.well-known/oauth-authorization-server`
307310
- `GET /.well-known/openid-configuration`
308311

309-
OAuth client registration, authorization, token, introspection, revocation, and
310-
userinfo endpoints are served by Better Auth under `/api/auth/oauth2/*`.
312+
OAuth authorization, token, introspection, revocation, and userinfo endpoints
313+
are served by Better Auth under `/api/auth/oauth2/*`. Modern clients can use
314+
CIMD, while existing clients can use Dynamic Client Registration (DCR); static
315+
pre-registered clients are also supported. OAuth tool access is
316+
default-deny using the scope map in `src/mcp/policy.ts`. Team API keys have full
317+
tool access to their fixed team, while browser session cookies are rejected.
318+
OAuth authorization requests must include an explicit, non-empty `scope` so a
319+
missing value cannot expand to the client's complete capability set.
311320
312321
MCP tools live in `src/mcp/tools/*` and cover contacts, templates, sequences,
313322
ESP settings (both the default-ESP singleton tools and the multi-ESP

apps/api/docs/mcp-2026-07-28-migration.md

Lines changed: 483 additions & 0 deletions
Large diffs are not rendered by default.

apps/api/docs/replace-oauth-server-with-better-auth.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
**PRD: Replace Custom OAuth2 With Better Auth**
22

3+
> Historical design note: its transport decisions are superseded by
4+
> [`mcp-2026-07-28-migration.md`](./mcp-2026-07-28-migration.md). The current
5+
> MCP implementation prefers CIMD and retains public Dynamic Client
6+
> Registration for existing clients.
7+
38
**Objective**
49
Replace SendLit’s custom OAuth2/auth implementation with Better Auth to support secure first-party web login, MCP OAuth, REST API authentication, and social login with Google plus Email OTP.
510

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
CREATE TABLE IF NOT EXISTS "oauth_client_assertion" (
2+
"id" text PRIMARY KEY NOT NULL,
3+
"expires_at" timestamp with time zone NOT NULL
4+
);
5+
--> statement-breakpoint
6+
CREATE TABLE IF NOT EXISTS "oauth_client_resource" (
7+
"id" text PRIMARY KEY NOT NULL,
8+
"client_id" text NOT NULL,
9+
"resource_id" text NOT NULL,
10+
"metadata" jsonb,
11+
"created_at" timestamp with time zone
12+
);
13+
--> statement-breakpoint
14+
CREATE TABLE IF NOT EXISTS "oauth_resource" (
15+
"id" text PRIMARY KEY NOT NULL,
16+
"identifier" text NOT NULL,
17+
"name" text NOT NULL,
18+
"access_token_ttl" integer,
19+
"refresh_token_ttl" integer,
20+
"signing_algorithm" text,
21+
"signing_key_id" text,
22+
"allowed_scopes" text[],
23+
"custom_claims" jsonb,
24+
"dpop_bound_access_tokens_required" boolean DEFAULT false NOT NULL,
25+
"disabled" boolean DEFAULT false NOT NULL,
26+
"created_at" timestamp with time zone,
27+
"updated_at" timestamp with time zone,
28+
"policy_version" integer DEFAULT 1 NOT NULL,
29+
"metadata" jsonb,
30+
CONSTRAINT "oauth_resource_identifier_unique" UNIQUE("identifier")
31+
);
32+
--> statement-breakpoint
33+
ALTER TABLE "oauth_access_token" ADD COLUMN "authorization_code_id" text;--> statement-breakpoint
34+
ALTER TABLE "oauth_access_token" ADD COLUMN "resources" text[];--> statement-breakpoint
35+
ALTER TABLE "oauth_access_token" ADD COLUMN "requested_user_info_claims" text[];--> statement-breakpoint
36+
ALTER TABLE "oauth_access_token" ADD COLUMN "confirmation" jsonb;--> statement-breakpoint
37+
ALTER TABLE "oauth_client" ADD COLUMN "client_discovery_id" text;--> statement-breakpoint
38+
ALTER TABLE "oauth_client" ADD COLUMN "client_credentials_scopes" text[] DEFAULT '{}' NOT NULL;--> statement-breakpoint
39+
ALTER TABLE "oauth_client" ADD COLUMN "backchannel_logout_uri" text;--> statement-breakpoint
40+
ALTER TABLE "oauth_client" ADD COLUMN "backchannel_logout_session_required" boolean;--> statement-breakpoint
41+
ALTER TABLE "oauth_client" ADD COLUMN "application_type" text;--> statement-breakpoint
42+
ALTER TABLE "oauth_client" ADD COLUMN "jwks" text;--> statement-breakpoint
43+
ALTER TABLE "oauth_client" ADD COLUMN "jwks_uri" text;--> statement-breakpoint
44+
ALTER TABLE "oauth_client" ADD COLUMN "dpop_bound_access_tokens" boolean DEFAULT false;--> statement-breakpoint
45+
ALTER TABLE "oauth_consent" ADD COLUMN "resources" text[];--> statement-breakpoint
46+
ALTER TABLE "oauth_consent" ADD COLUMN "requested_user_info_claims" text[];--> statement-breakpoint
47+
ALTER TABLE "oauth_refresh_token" ADD COLUMN "authorization_code_id" text;--> statement-breakpoint
48+
ALTER TABLE "oauth_refresh_token" ADD COLUMN "resources" text[];--> statement-breakpoint
49+
ALTER TABLE "oauth_refresh_token" ADD COLUMN "requested_user_info_claims" text[];--> statement-breakpoint
50+
ALTER TABLE "oauth_refresh_token" ADD COLUMN "rotated_at" timestamp with time zone;--> statement-breakpoint
51+
ALTER TABLE "oauth_refresh_token" ADD COLUMN "rotation_replay_response" text;--> statement-breakpoint
52+
ALTER TABLE "oauth_refresh_token" ADD COLUMN "rotation_replay_expires_at" timestamp with time zone;--> statement-breakpoint
53+
ALTER TABLE "oauth_refresh_token" ADD COLUMN "confirmation" jsonb;--> statement-breakpoint
54+
DO $$ BEGIN
55+
ALTER TABLE "oauth_client_resource" ADD CONSTRAINT "oauth_client_resource_client_id_oauth_client_client_id_fk" FOREIGN KEY ("client_id") REFERENCES "public"."oauth_client"("client_id") ON DELETE cascade ON UPDATE no action;
56+
EXCEPTION
57+
WHEN duplicate_object THEN null;
58+
END $$;
59+
--> statement-breakpoint
60+
DO $$ BEGIN
61+
ALTER TABLE "oauth_client_resource" ADD CONSTRAINT "oauth_client_resource_resource_id_oauth_resource_identifier_fk" FOREIGN KEY ("resource_id") REFERENCES "public"."oauth_resource"("identifier") ON DELETE cascade ON UPDATE no action;
62+
EXCEPTION
63+
WHEN duplicate_object THEN null;
64+
END $$;
65+
--> statement-breakpoint
66+
CREATE INDEX IF NOT EXISTS "auth_oauth_client_resource_client_id_idx" ON "oauth_client_resource" USING btree ("client_id");--> statement-breakpoint
67+
CREATE INDEX IF NOT EXISTS "auth_oauth_client_resource_resource_id_idx" ON "oauth_client_resource" USING btree ("resource_id");--> statement-breakpoint
68+
CREATE UNIQUE INDEX IF NOT EXISTS "auth_oauth_client_resource_client_id_resource_id_idx" ON "oauth_client_resource" USING btree ("client_id","resource_id");--> statement-breakpoint
69+
CREATE INDEX IF NOT EXISTS "auth_oauth_access_token_authorization_code_id_idx" ON "oauth_access_token" USING btree ("authorization_code_id");--> statement-breakpoint
70+
CREATE INDEX IF NOT EXISTS "auth_oauth_refresh_token_authorization_code_id_idx" ON "oauth_refresh_token" USING btree ("authorization_code_id");

0 commit comments

Comments
 (0)