@ainecto/mcp 0.1.4 → 0.3.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/dist/bin/mcp.js CHANGED
@@ -2,9 +2,13 @@
2
2
 
3
3
  // src/core/config/endpoints.ts
4
4
  var DEFAULT_ENDPOINTS = {
5
- prod: "https://ainecto.com/mcp",
6
- dev: "https://dev.ainecto.com/mcp"
5
+ prod: "https://ai-erd.com/mcp",
6
+ dev: "https://dev.ai-erd.com/mcp"
7
7
  };
8
+ var LEGACY_DEFAULT_ENDPOINTS = [
9
+ "https://ainecto.com/mcp",
10
+ "https://dev.ainecto.com/mcp"
11
+ ];
8
12
  function resolveEndpoint(input = {}) {
9
13
  const envVars = input.envVars ?? process.env;
10
14
  const env = input.env ?? "prod";
@@ -24,7 +28,7 @@ function normalizeEndpoint(endpoint) {
24
28
  }
25
29
  function isDefaultEndpoint(endpoint) {
26
30
  const normalized = normalizeEndpoint(endpoint);
27
- return Object.values(DEFAULT_ENDPOINTS).includes(normalized);
31
+ return Object.values(DEFAULT_ENDPOINTS).includes(normalized) || LEGACY_DEFAULT_ENDPOINTS.includes(normalized);
28
32
  }
29
33
  function assertTrustedEndpointUrl(value, label = "URL") {
30
34
  const url = typeof value === "string" ? new URL(value) : value;
@@ -66,18 +70,18 @@ var FileTokenStore = class {
66
70
  constructor(rootDir = join(homedir(), ".ainecto")) {
67
71
  this.filePath = join(rootDir, "tokens.json");
68
72
  }
69
- async load(endpoint) {
73
+ async load(endpoint, role) {
70
74
  const file = await this.readFile();
71
- return file[tokenKey(endpoint)];
75
+ return file[tokenKey(endpoint, role)];
72
76
  }
73
- async save(endpoint, token) {
77
+ async save(endpoint, token, role) {
74
78
  const file = await this.readFile();
75
- file[tokenKey(endpoint)] = { ...token, endpoint, updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
79
+ file[tokenKey(endpoint, role)] = { ...token, endpoint, updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
76
80
  await this.writeFile(file);
77
81
  }
78
- async delete(endpoint) {
82
+ async delete(endpoint, role) {
79
83
  const file = await this.readFile();
80
- delete file[tokenKey(endpoint)];
84
+ delete file[tokenKey(endpoint, role)];
81
85
  await this.writeFile(file);
82
86
  }
83
87
  async readFile() {
@@ -112,8 +116,9 @@ var FileTokenStore = class {
112
116
  await chmodIfPermissive(this.filePath, 384);
113
117
  }
114
118
  };
115
- function tokenKey(endpoint) {
116
- return createHash("sha256").update(endpoint).digest("hex");
119
+ function tokenKey(endpoint, role) {
120
+ const material = role && role.trim() ? `${endpoint}#role=${role.trim().toLowerCase()}` : endpoint;
121
+ return createHash("sha256").update(material).digest("hex");
117
122
  }
118
123
  function isNodeError(error, code) {
119
124
  return error instanceof Error && "code" in error && error.code === code;
@@ -169,6 +174,31 @@ function isRecord(value) {
169
174
  return typeof value === "object" && value !== null && !Array.isArray(value);
170
175
  }
171
176
 
177
+ // src/core/harness/role.ts
178
+ var HARNESS_ROLES = ["design", "development", "test", "validation"];
179
+ var ROLE_SCOPE_PREFIX = "ai-erd:role:";
180
+ var ROLE_HEADER = "X-AI-ERD-Role";
181
+ var ROLE_ENV_VAR = "AI_ERD_ROLE";
182
+ function resolveRole(input = {}) {
183
+ if (input.role !== void 0) {
184
+ return { role: assertRole(input.role), source: "flag" };
185
+ }
186
+ const fromEnv = (input.envVars ?? process.env)[ROLE_ENV_VAR];
187
+ if (fromEnv && fromEnv.trim()) {
188
+ return { role: assertRole(fromEnv), source: "env" };
189
+ }
190
+ return { source: "none" };
191
+ }
192
+ function assertRole(value) {
193
+ const normalized = value.trim().toLowerCase();
194
+ if (HARNESS_ROLES.includes(normalized)) {
195
+ return normalized;
196
+ }
197
+ throw new Error(
198
+ `Invalid role "${value}". Expected one of: ${HARNESS_ROLES.join(", ")}.`
199
+ );
200
+ }
201
+
172
202
  // src/core/auth/oauth.ts
173
203
  var OAuthClient = class {
174
204
  constructor(options) {
@@ -187,7 +217,7 @@ var OAuthClient = class {
187
217
  assertEnvTokenEndpointAllowed(this.options.endpoint, this.envVars);
188
218
  return envToken;
189
219
  }
190
- const stored = await this.options.tokenStore.load(this.options.endpoint);
220
+ const stored = await this.options.tokenStore.load(this.options.endpoint, this.options.role);
191
221
  if (!stored) {
192
222
  return void 0;
193
223
  }
@@ -197,7 +227,7 @@ var OAuthClient = class {
197
227
  return this.refreshStoredToken(stored);
198
228
  }
199
229
  async refreshAfterUnauthorized() {
200
- const stored = await this.options.tokenStore.load(this.options.endpoint);
230
+ const stored = await this.options.tokenStore.load(this.options.endpoint, this.options.role);
201
231
  if (!stored?.refreshToken) {
202
232
  return void 0;
203
233
  }
@@ -218,6 +248,9 @@ var OAuthClient = class {
218
248
  authorizeUrl.searchParams.set("code_challenge_method", "S256");
219
249
  authorizeUrl.searchParams.set("resource", this.options.endpoint);
220
250
  authorizeUrl.searchParams.set("state", state);
251
+ if (this.options.role) {
252
+ authorizeUrl.searchParams.set("scope", `mcp ${ROLE_SCOPE_PREFIX}${this.options.role}`);
253
+ }
221
254
  assertTrustedEndpointUrl(authorizeUrl, "OAuth authorization URL");
222
255
  await this.openBrowserImpl(authorizeUrl.toString());
223
256
  const code = await loopback.waitForCode();
@@ -231,14 +264,14 @@ var OAuthClient = class {
231
264
  ...registration.clientSecret ? { client_secret: registration.clientSecret } : {}
232
265
  }, this.fetchImpl);
233
266
  const stored = toStoredToken(this.options.endpoint, token, metadata, registration);
234
- await this.options.tokenStore.save(this.options.endpoint, stored);
267
+ await this.options.tokenStore.save(this.options.endpoint, stored, this.options.role);
235
268
  return stored;
236
269
  } finally {
237
270
  await loopback.close();
238
271
  }
239
272
  }
240
273
  async logout() {
241
- await this.options.tokenStore.delete(this.options.endpoint);
274
+ await this.options.tokenStore.delete(this.options.endpoint, this.options.role);
242
275
  }
243
276
  async refreshStoredToken(stored) {
244
277
  if (!stored.refreshToken) {
@@ -253,7 +286,7 @@ var OAuthClient = class {
253
286
  resource: this.options.endpoint
254
287
  }, this.fetchImpl);
255
288
  const next = toStoredToken(this.options.endpoint, token, metadata, stored);
256
- await this.options.tokenStore.save(this.options.endpoint, next);
289
+ await this.options.tokenStore.save(this.options.endpoint, next, this.options.role);
257
290
  return next.accessToken;
258
291
  }
259
292
  };
@@ -526,6 +559,9 @@ var McpRpcClient = class {
526
559
  if (token) {
527
560
  headers.authorization = `Bearer ${token}`;
528
561
  }
562
+ if (this.options.role) {
563
+ headers[ROLE_HEADER.toLowerCase()] = this.options.role;
564
+ }
529
565
  return this.fetchImpl(this.options.endpoint, {
530
566
  method: "POST",
531
567
  headers,
@@ -595,8 +631,12 @@ function isRecord3(value) {
595
631
  // src/adapters/mcp/connector.ts
596
632
  async function runConnector(options) {
597
633
  const tokenStore = new FileTokenStore();
598
- const auth = new OAuthClient({ endpoint: options.endpoint, tokenStore });
599
- const client = new McpRpcClient({ endpoint: options.endpoint, tokenProvider: auth });
634
+ const auth = new OAuthClient({ endpoint: options.endpoint, tokenStore, role: options.role });
635
+ const client = new McpRpcClient({
636
+ endpoint: options.endpoint,
637
+ tokenProvider: auth,
638
+ role: options.role
639
+ });
600
640
  await runStdioBridge({
601
641
  input: options.input,
602
642
  output: options.output,
@@ -672,6 +712,8 @@ function parseMcpArgs(argv) {
672
712
  result.env = assertEnv(requireFlagValue(arg, argv[++index]));
673
713
  } else if (arg === "--endpoint") {
674
714
  result.endpoint = requireFlagValue(arg, argv[++index]);
715
+ } else if (arg === "--role") {
716
+ result.role = assertRole(requireFlagValue(arg, argv[++index]));
675
717
  } else if (arg === "--help" || arg === "-h") {
676
718
  result.help = true;
677
719
  } else {
@@ -691,12 +733,17 @@ function requireFlagValue(flag, value) {
691
733
  try {
692
734
  const args = parseMcpArgs(process.argv.slice(2));
693
735
  if (args.help) {
694
- process.stdout.write("Usage: mcp [--env prod|dev] [--endpoint URL]\n");
736
+ process.stdout.write(
737
+ `Usage: mcp [--env prod|dev] [--endpoint URL] [--role ${HARNESS_ROLES.join("|")}]
738
+ `
739
+ );
695
740
  process.exit(0);
696
741
  }
697
742
  const resolved = resolveEndpoint({ env: args.env, endpoint: args.endpoint });
743
+ const resolvedRole = resolveRole({ role: args.role });
698
744
  await runConnector({
699
745
  endpoint: resolved.endpoint,
746
+ role: resolvedRole.role,
700
747
  input: process.stdin,
701
748
  output: process.stdout,
702
749
  errorOutput: process.stderr
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/core/config/endpoints.ts","../../src/core/auth/tokenStore.ts","../../src/core/auth/oauth.ts","../../src/core/auth/clientRegistration.ts","../../src/core/mcp/rpcClient.ts","../../src/core/mcp/stdioBridge.ts","../../src/adapters/mcp/connector.ts","../../src/core/output/render.ts","../../src/adapters/mcp/args.ts","../../src/bin/mcp.ts"],"sourcesContent":["export type AinectoEnv = \"prod\" | \"dev\";\n\nexport interface EndpointResolutionInput {\n env?: AinectoEnv;\n endpoint?: string;\n envVars?: NodeJS.ProcessEnv;\n}\n\nexport interface ResolvedEndpoint {\n env: AinectoEnv;\n endpoint: string;\n source: \"flag\" | \"env\" | \"default\";\n}\n\nconst DEFAULT_ENDPOINTS: Record<AinectoEnv, string> = {\n prod: \"https://ainecto.com/mcp\",\n dev: \"https://dev.ainecto.com/mcp\",\n};\n\nexport function resolveEndpoint(input: EndpointResolutionInput = {}): ResolvedEndpoint {\n const envVars = input.envVars ?? process.env;\n const env = input.env ?? \"prod\";\n\n if (input.endpoint) {\n return { env, endpoint: normalizeEndpoint(input.endpoint), source: \"flag\" };\n }\n\n if (envVars.AINECTO_MCP_ENDPOINT) {\n return { env, endpoint: normalizeEndpoint(envVars.AINECTO_MCP_ENDPOINT), source: \"env\" };\n }\n\n return { env, endpoint: DEFAULT_ENDPOINTS[env], source: \"default\" };\n}\n\nexport function normalizeEndpoint(endpoint: string): string {\n const url = new URL(endpoint);\n assertTrustedEndpointUrl(url, \"MCP endpoint\");\n url.hash = \"\";\n return url.toString().replace(/\\/$/, \"\");\n}\n\nexport function isDefaultEndpoint(endpoint: string): boolean {\n const normalized = normalizeEndpoint(endpoint);\n return Object.values(DEFAULT_ENDPOINTS).includes(normalized);\n}\n\nexport function assertTrustedEndpointUrl(value: string | URL, label = \"URL\"): void {\n const url = typeof value === \"string\" ? new URL(value) : value;\n if (url.protocol === \"https:\") {\n return;\n }\n if (url.protocol === \"http:\" && isLoopbackHostname(url.hostname)) {\n return;\n }\n throw new Error(`${label} must use https, except http is allowed for localhost loopback endpoints.`);\n}\n\nexport function assertLoopbackRedirectUrl(value: string): void {\n const url = new URL(value);\n if (url.protocol === \"http:\" && isLoopbackHostname(url.hostname)) {\n return;\n }\n throw new Error(\"OAuth redirect URI must be an http localhost loopback URL.\");\n}\n\nfunction isLoopbackHostname(hostname: string): boolean {\n return hostname === \"localhost\"\n || hostname === \"127.0.0.1\"\n || hostname === \"::1\"\n || hostname === \"[::1]\";\n}\n\nexport function assertEnv(value: string | undefined): AinectoEnv | undefined {\n if (value === undefined) {\n return undefined;\n }\n if (value === \"prod\" || value === \"dev\") {\n return value;\n }\n throw new Error(`Invalid --env value \"${value}\". Expected \"prod\" or \"dev\".`);\n}\n","import { createHash } from \"node:crypto\";\nimport { mkdir, readFile, rename, rm, stat, writeFile, chmod } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\n\nexport interface StoredTokenSet {\n endpoint: string;\n accessToken: string;\n refreshToken?: string;\n tokenType?: string;\n expiresAt?: number;\n scope?: string;\n clientId?: string;\n clientSecret?: string;\n authorizationServer?: string;\n updatedAt: string;\n}\n\nexport interface TokenStore {\n load(endpoint: string): Promise<StoredTokenSet | undefined>;\n save(endpoint: string, token: StoredTokenSet): Promise<void>;\n delete(endpoint: string): Promise<void>;\n}\n\ntype TokenFile = Record<string, StoredTokenSet>;\n\nexport class FileTokenStore implements TokenStore {\n readonly filePath: string;\n\n constructor(rootDir = join(homedir(), \".ainecto\")) {\n this.filePath = join(rootDir, \"tokens.json\");\n }\n\n async load(endpoint: string): Promise<StoredTokenSet | undefined> {\n const file = await this.readFile();\n return file[tokenKey(endpoint)];\n }\n\n async save(endpoint: string, token: StoredTokenSet): Promise<void> {\n const file = await this.readFile();\n file[tokenKey(endpoint)] = { ...token, endpoint, updatedAt: new Date().toISOString() };\n await this.writeFile(file);\n }\n\n async delete(endpoint: string): Promise<void> {\n const file = await this.readFile();\n delete file[tokenKey(endpoint)];\n await this.writeFile(file);\n }\n\n private async readFile(): Promise<TokenFile> {\n try {\n await this.hardenExistingPermissions();\n const raw = await readFile(this.filePath, \"utf8\");\n const parsed = JSON.parse(raw) as unknown;\n if (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n throw new Error(\"Token file must contain an object.\");\n }\n return parsed as TokenFile;\n } catch (error) {\n if (isNodeError(error, \"ENOENT\")) {\n return {};\n }\n throw error;\n }\n }\n\n private async writeFile(file: TokenFile): Promise<void> {\n await mkdir(dirname(this.filePath), { recursive: true, mode: 0o700 });\n await chmod(dirname(this.filePath), 0o700);\n const tmpPath = `${this.filePath}.${process.pid}.${Date.now()}.tmp`;\n await writeFile(tmpPath, `${JSON.stringify(file, null, 2)}\\n`, { mode: 0o600 });\n await chmod(tmpPath, 0o600);\n await rename(tmpPath, this.filePath);\n await chmod(this.filePath, 0o600);\n }\n\n private async hardenExistingPermissions(): Promise<void> {\n const dirPath = dirname(this.filePath);\n await chmodIfPermissive(dirPath, 0o700);\n await chmodIfPermissive(this.filePath, 0o600);\n }\n}\n\nexport function tokenKey(endpoint: string): string {\n return createHash(\"sha256\").update(endpoint).digest(\"hex\");\n}\n\nexport async function tokenStorePermissions(path: string): Promise<{ mode: number } | undefined> {\n try {\n const result = await stat(path);\n return { mode: result.mode & 0o777 };\n } catch (error) {\n if (isNodeError(error, \"ENOENT\")) {\n return undefined;\n }\n throw error;\n }\n}\n\nexport async function tokenStoreDirectoryPermissions(path: string): Promise<{ mode: number } | undefined> {\n return tokenStorePermissions(dirname(path));\n}\n\nexport async function removeTokenStoreForTests(path: string): Promise<void> {\n await rm(dirname(path), { recursive: true, force: true });\n}\n\nfunction isNodeError(error: unknown, code: string): error is NodeJS.ErrnoException {\n return error instanceof Error && \"code\" in error && error.code === code;\n}\n\nasync function chmodIfPermissive(path: string, mode: number): Promise<void> {\n try {\n const result = await stat(path);\n if ((result.mode & 0o077) !== 0) {\n await chmod(path, mode);\n }\n } catch (error) {\n if (isNodeError(error, \"ENOENT\")) {\n return;\n }\n throw error;\n }\n}\n","import { createHash, randomBytes } from \"node:crypto\";\nimport { createServer } from \"node:http\";\nimport { spawn } from \"node:child_process\";\nimport { URLSearchParams } from \"node:url\";\nimport type { StoredTokenSet, TokenStore } from \"./tokenStore\";\nimport { registerPublicClient, type ClientRegistrationResult } from \"./clientRegistration\";\nimport { assertTrustedEndpointUrl, isDefaultEndpoint } from \"../config/endpoints\";\n\nexport interface OAuthClientOptions {\n endpoint: string;\n tokenStore: TokenStore;\n fetchImpl?: typeof fetch;\n envVars?: NodeJS.ProcessEnv;\n openBrowser?: (url: string) => Promise<void>;\n}\n\nexport interface OAuthMetadata {\n authorizationEndpoint: string;\n tokenEndpoint: string;\n registrationEndpoint?: string;\n issuer?: string;\n codeChallengeMethodsSupported: string[];\n}\n\nexport interface TokenProvider {\n getAccessToken(): Promise<string | undefined>;\n refreshAfterUnauthorized(): Promise<string | undefined>;\n}\n\nexport class OAuthClient implements TokenProvider {\n private readonly fetchImpl: typeof fetch;\n private readonly envVars: NodeJS.ProcessEnv;\n private readonly openBrowserImpl: (url: string) => Promise<void>;\n\n constructor(private readonly options: OAuthClientOptions) {\n this.fetchImpl = options.fetchImpl ?? fetch;\n this.envVars = options.envVars ?? process.env;\n this.openBrowserImpl = options.openBrowser ?? openBrowser;\n }\n\n async getAccessToken(): Promise<string | undefined> {\n const envToken = this.envVars.AINECTO_TOKEN;\n if (envToken) {\n assertEnvTokenEndpointAllowed(this.options.endpoint, this.envVars);\n return envToken;\n }\n\n const stored = await this.options.tokenStore.load(this.options.endpoint);\n if (!stored) {\n return undefined;\n }\n\n if (!shouldRefresh(stored)) {\n return stored.accessToken;\n }\n\n return this.refreshStoredToken(stored);\n }\n\n async refreshAfterUnauthorized(): Promise<string | undefined> {\n const stored = await this.options.tokenStore.load(this.options.endpoint);\n if (!stored?.refreshToken) {\n return undefined;\n }\n return this.refreshStoredToken(stored);\n }\n\n async login(): Promise<StoredTokenSet> {\n const pkce = generatePkcePair();\n const state = generateOAuthState();\n const loopback = await createLoopbackReceiver(state);\n\n try {\n const metadata = await discoverOAuthMetadata(this.options.endpoint, this.fetchImpl);\n const registration = metadata.registrationEndpoint\n ? await registerPublicClient(metadata.registrationEndpoint, loopback.redirectUri, this.fetchImpl)\n : { clientId: \"ainecto-cli\" };\n const authorizeUrl = new URL(metadata.authorizationEndpoint);\n authorizeUrl.searchParams.set(\"response_type\", \"code\");\n authorizeUrl.searchParams.set(\"client_id\", registration.clientId);\n authorizeUrl.searchParams.set(\"redirect_uri\", loopback.redirectUri);\n authorizeUrl.searchParams.set(\"code_challenge\", pkce.codeChallenge);\n authorizeUrl.searchParams.set(\"code_challenge_method\", \"S256\");\n authorizeUrl.searchParams.set(\"resource\", this.options.endpoint);\n authorizeUrl.searchParams.set(\"state\", state);\n\n assertTrustedEndpointUrl(authorizeUrl, \"OAuth authorization URL\");\n await this.openBrowserImpl(authorizeUrl.toString());\n const code = await loopback.waitForCode();\n const token = await exchangeToken(metadata.tokenEndpoint, {\n grant_type: \"authorization_code\",\n code,\n redirect_uri: loopback.redirectUri,\n client_id: registration.clientId,\n code_verifier: pkce.codeVerifier,\n resource: this.options.endpoint,\n ...(registration.clientSecret ? { client_secret: registration.clientSecret } : {}),\n }, this.fetchImpl);\n\n const stored = toStoredToken(this.options.endpoint, token, metadata, registration);\n await this.options.tokenStore.save(this.options.endpoint, stored);\n return stored;\n } finally {\n await loopback.close();\n }\n }\n\n async logout(): Promise<void> {\n await this.options.tokenStore.delete(this.options.endpoint);\n }\n\n private async refreshStoredToken(stored: StoredTokenSet): Promise<string | undefined> {\n if (!stored.refreshToken) {\n return stored.accessToken;\n }\n const metadata = await discoverOAuthMetadata(this.options.endpoint, this.fetchImpl);\n const token = await exchangeToken(metadata.tokenEndpoint, {\n grant_type: \"refresh_token\",\n refresh_token: stored.refreshToken,\n client_id: stored.clientId ?? \"ainecto-cli\",\n ...(stored.clientSecret ? { client_secret: stored.clientSecret } : {}),\n resource: this.options.endpoint,\n }, this.fetchImpl);\n const next = toStoredToken(this.options.endpoint, token, metadata, stored);\n await this.options.tokenStore.save(this.options.endpoint, next);\n return next.accessToken;\n }\n}\n\nexport function generatePkcePair(): { codeVerifier: string; codeChallenge: string } {\n const codeVerifier = randomBytes(32).toString(\"base64url\");\n const codeChallenge = createHash(\"sha256\").update(codeVerifier).digest(\"base64url\");\n return { codeVerifier, codeChallenge };\n}\n\nexport function generateOAuthState(): string {\n return randomBytes(32).toString(\"base64url\");\n}\n\nexport function shouldRefresh(token: Pick<StoredTokenSet, \"expiresAt\">, now = Date.now()): boolean {\n if (!token.expiresAt) {\n return false;\n }\n return token.expiresAt - now < 60_000;\n}\n\nexport async function discoverOAuthMetadata(endpoint: string, fetchImpl: typeof fetch = fetch): Promise<OAuthMetadata> {\n assertTrustedEndpointUrl(endpoint, \"MCP endpoint\");\n const resourceMetadataUrl = await discoverResourceMetadataUrl(endpoint, fetchImpl);\n assertTrustedEndpointUrl(resourceMetadataUrl, \"OAuth protected resource metadata URL\");\n const resourceMetadata = await fetchJson<Record<string, unknown>>(resourceMetadataUrl, fetchImpl);\n const authorizationServers = resourceMetadata.authorization_servers;\n if (!Array.isArray(authorizationServers) || typeof authorizationServers[0] !== \"string\") {\n throw new Error(\"OAuth protected resource metadata did not include authorization_servers.\");\n }\n const authServer = authorizationServers[0];\n assertTrustedEndpointUrl(authServer, \"OAuth authorization server\");\n const metadataUrl = authServer.includes(\"/.well-known/\")\n ? authServer\n : `${authServer.replace(/\\/$/, \"\")}/.well-known/oauth-authorization-server`;\n assertTrustedEndpointUrl(metadataUrl, \"OAuth authorization server metadata URL\");\n const metadata = await fetchJson<Record<string, unknown>>(metadataUrl, fetchImpl);\n if (typeof metadata.authorization_endpoint !== \"string\" || typeof metadata.token_endpoint !== \"string\") {\n throw new Error(\"OAuth authorization server metadata is missing authorization_endpoint or token_endpoint.\");\n }\n assertTrustedEndpointUrl(metadata.authorization_endpoint, \"OAuth authorization endpoint\");\n assertTrustedEndpointUrl(metadata.token_endpoint, \"OAuth token endpoint\");\n if (typeof metadata.registration_endpoint === \"string\") {\n assertTrustedEndpointUrl(metadata.registration_endpoint, \"OAuth client registration endpoint\");\n }\n if (typeof metadata.issuer === \"string\") {\n assertTrustedEndpointUrl(metadata.issuer, \"OAuth issuer\");\n }\n const codeChallengeMethodsSupported = parseStringArray(metadata.code_challenge_methods_supported);\n if (!codeChallengeMethodsSupported.includes(\"S256\")) {\n throw new Error(\"OAuth authorization server metadata must support PKCE S256.\");\n }\n return {\n authorizationEndpoint: metadata.authorization_endpoint,\n tokenEndpoint: metadata.token_endpoint,\n registrationEndpoint: typeof metadata.registration_endpoint === \"string\" ? metadata.registration_endpoint : undefined,\n issuer: typeof metadata.issuer === \"string\" ? metadata.issuer : undefined,\n codeChallengeMethodsSupported,\n };\n}\n\nasync function discoverResourceMetadataUrl(endpoint: string, fetchImpl: typeof fetch): Promise<string> {\n const challengeUrl = new URL(endpoint);\n assertTrustedEndpointUrl(challengeUrl, \"MCP endpoint\");\n const response = await fetchImpl(challengeUrl, { method: \"GET\" });\n const challenge = response.headers.get(\"www-authenticate\");\n const fromChallenge = challenge ? parseBearerChallengeParam(challenge, \"resource_metadata\") : undefined;\n if (fromChallenge) {\n assertTrustedEndpointUrl(fromChallenge, \"OAuth protected resource metadata URL\");\n return fromChallenge;\n }\n const origin = new URL(endpoint).origin;\n const fallback = `${origin}/.well-known/oauth-protected-resource`;\n assertTrustedEndpointUrl(fallback, \"OAuth protected resource metadata URL\");\n return fallback;\n}\n\nexport function parseBearerChallengeParam(header: string, name: string): string | undefined {\n const pattern = new RegExp(`${name}=\"([^\"]+)\"`);\n return pattern.exec(header)?.[1];\n}\n\nasync function exchangeToken(\n tokenEndpoint: string,\n params: Record<string, string>,\n fetchImpl: typeof fetch,\n): Promise<Record<string, unknown>> {\n assertTrustedEndpointUrl(tokenEndpoint, \"OAuth token endpoint\");\n const response = await fetchImpl(tokenEndpoint, {\n method: \"POST\",\n headers: { \"content-type\": \"application/x-www-form-urlencoded\" },\n body: new URLSearchParams(params),\n });\n if (!response.ok) {\n throw new Error(`OAuth token exchange failed with HTTP ${response.status}.`);\n }\n return response.json() as Promise<Record<string, unknown>>;\n}\n\ntype TokenContext = Partial<Pick<StoredTokenSet, \"refreshToken\" | \"tokenType\" | \"expiresAt\" | \"scope\" | \"clientId\" | \"clientSecret\">>\n & Partial<ClientRegistrationResult>;\n\nfunction toStoredToken(\n endpoint: string,\n token: Record<string, unknown>,\n metadata: OAuthMetadata,\n previous?: TokenContext,\n): StoredTokenSet {\n if (typeof token.access_token !== \"string\") {\n throw new Error(\"OAuth token response did not include access_token.\");\n }\n const expiresIn = typeof token.expires_in === \"number\" ? token.expires_in : undefined;\n return {\n endpoint,\n accessToken: token.access_token,\n refreshToken: typeof token.refresh_token === \"string\" ? token.refresh_token : previous?.refreshToken,\n tokenType: typeof token.token_type === \"string\" ? token.token_type : previous?.tokenType,\n expiresAt: expiresIn ? Date.now() + expiresIn * 1000 : previous?.expiresAt,\n scope: typeof token.scope === \"string\" ? token.scope : previous?.scope,\n clientId: previous?.clientId ?? \"ainecto-cli\",\n clientSecret: previous?.clientSecret,\n authorizationServer: metadata.issuer,\n updatedAt: new Date().toISOString(),\n };\n}\n\nasync function createLoopbackReceiver(expectedState: string): Promise<{\n redirectUri: string;\n waitForCode(): Promise<string>;\n close(): Promise<void>;\n}> {\n let resolveCode!: (code: string) => void;\n let rejectCode!: (error: Error) => void;\n const codePromise = new Promise<string>((resolve, reject) => {\n resolveCode = resolve;\n rejectCode = reject;\n });\n codePromise.catch(() => undefined);\n\n const server = createServer((req, res) => {\n const url = new URL(req.url ?? \"/\", \"http://127.0.0.1\");\n const error = url.searchParams.get(\"error\");\n const code = url.searchParams.get(\"code\");\n const state = url.searchParams.get(\"state\");\n if (error) {\n res.writeHead(400, { \"content-type\": \"text/plain\" });\n res.end(\"Ainecto CLI authorization failed. You can close this tab.\");\n rejectCode(new Error(`OAuth authorization failed: ${error}`));\n return;\n }\n if (!state || state !== expectedState) {\n res.writeHead(400, { \"content-type\": \"text/plain\" });\n res.end(\"Ainecto CLI authorization state mismatch. You can close this tab.\");\n rejectCode(new Error(\"OAuth state mismatch.\"));\n return;\n }\n if (!code) {\n res.writeHead(400, { \"content-type\": \"text/plain\" });\n res.end(\"Missing OAuth code.\");\n rejectCode(new Error(\"OAuth redirect did not include a code.\"));\n return;\n }\n res.writeHead(200, { \"content-type\": \"text/plain\" });\n res.end(\"Ainecto CLI authorization complete. You can close this tab.\");\n resolveCode(code);\n });\n\n await new Promise<void>((resolve) => server.listen(0, \"127.0.0.1\", resolve));\n const address = server.address();\n if (!address || typeof address === \"string\") {\n throw new Error(\"Loopback OAuth server did not bind to a TCP port.\");\n }\n return {\n redirectUri: `http://127.0.0.1:${address.port}/callback`,\n waitForCode: () => codePromise,\n close: () => new Promise<void>((resolve, reject) => server.close((error) => error ? reject(error) : resolve())),\n };\n}\n\nfunction parseStringArray(value: unknown): string[] {\n return Array.isArray(value) ? value.filter((item): item is string => typeof item === \"string\") : [];\n}\n\nasync function fetchJson<T>(url: string, fetchImpl: typeof fetch): Promise<T> {\n assertTrustedEndpointUrl(url, \"OAuth metadata URL\");\n const response = await fetchImpl(url);\n if (!response.ok) {\n throw new Error(`Failed to fetch OAuth metadata from ${url}: HTTP ${response.status}.`);\n }\n return response.json() as Promise<T>;\n}\n\nexport function getBrowserOpenCommand(\n url: string,\n platform: NodeJS.Platform = process.platform,\n): { command: string; args: string[] } {\n assertTrustedEndpointUrl(url, \"OAuth authorization URL\");\n if (platform === \"darwin\") {\n return { command: \"open\", args: [url] };\n }\n if (platform === \"win32\") {\n return { command: \"explorer.exe\", args: [url] };\n }\n return { command: \"xdg-open\", args: [url] };\n}\n\nasync function openBrowser(url: string): Promise<void> {\n const { command, args } = getBrowserOpenCommand(url);\n const child = spawn(command, args, { stdio: \"ignore\", detached: true });\n child.unref();\n}\n\nfunction assertEnvTokenEndpointAllowed(endpoint: string, envVars: NodeJS.ProcessEnv): void {\n if (envVars.AINECTO_ALLOW_CUSTOM_ENDPOINT_TOKEN === \"1\") {\n return;\n }\n if (isDefaultEndpoint(endpoint)) {\n return;\n }\n throw new Error(\"AINECTO_TOKEN can only be used with the default prod/dev endpoints. Set AINECTO_ALLOW_CUSTOM_ENDPOINT_TOKEN=1 only when you intentionally trust the custom endpoint.\");\n}\n","import { assertLoopbackRedirectUrl, assertTrustedEndpointUrl } from \"../config/endpoints\";\n\nexport interface ClientRegistrationResult {\n clientId: string;\n clientSecret?: string;\n}\n\nexport async function registerPublicClient(\n registrationEndpoint: string,\n redirectUri: string,\n fetchImpl: typeof fetch = fetch,\n): Promise<ClientRegistrationResult> {\n assertTrustedEndpointUrl(registrationEndpoint, \"OAuth client registration endpoint\");\n assertLoopbackRedirectUrl(redirectUri);\n const response = await fetchImpl(registrationEndpoint, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\", accept: \"application/json\" },\n body: JSON.stringify({\n client_name: \"Ainecto CLI\",\n redirect_uris: [redirectUri],\n token_endpoint_auth_method: \"none\",\n grant_types: [\"authorization_code\", \"refresh_token\"],\n response_types: [\"code\"],\n }),\n });\n if (!response.ok) {\n throw new Error(`OAuth client registration failed with HTTP ${response.status}.`);\n }\n const body = await response.json() as unknown;\n if (!isRecord(body) || typeof body.client_id !== \"string\") {\n throw new Error(\"OAuth client registration response did not include client_id.\");\n }\n return {\n clientId: body.client_id,\n clientSecret: typeof body.client_secret === \"string\" ? body.client_secret : undefined,\n };\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n","import type { TokenProvider } from \"../auth/oauth\";\n\nexport interface JsonRpcRequest {\n jsonrpc: \"2.0\";\n id?: string | number | null;\n method: string;\n params?: unknown;\n}\n\nexport interface JsonRpcSuccess {\n jsonrpc: \"2.0\";\n id?: string | number | null;\n result: unknown;\n}\n\nexport interface JsonRpcFailure {\n jsonrpc: \"2.0\";\n id?: string | number | null;\n error: {\n code: number;\n message: string;\n data?: unknown;\n };\n}\n\nexport type JsonRpcResponse = JsonRpcSuccess | JsonRpcFailure;\n\nexport interface McpRpcClientOptions {\n endpoint: string;\n tokenProvider?: TokenProvider;\n fetchImpl?: typeof fetch;\n envVars?: NodeJS.ProcessEnv;\n}\n\nexport class McpRpcError extends Error {\n constructor(\n message: string,\n readonly code: string,\n readonly details?: unknown,\n ) {\n super(message);\n }\n}\n\nexport class McpRpcClient {\n private readonly fetchImpl: typeof fetch;\n private nextId = 1;\n\n constructor(private readonly options: McpRpcClientOptions) {\n this.fetchImpl = options.fetchImpl ?? fetch;\n }\n\n initialize(): Promise<unknown> {\n return this.request(\"initialize\", {\n protocolVersion: \"2024-11-05\",\n capabilities: {},\n clientInfo: { name: \"@ainecto/mcp\", version: \"0.1.0\" },\n });\n }\n\n async toolsList(): Promise<unknown[]> {\n const result = await this.request(\"tools/list\", {});\n if (!isRecord(result) || !Array.isArray(result.tools)) {\n throw new McpRpcError(\"tools/list response did not include a tools array.\", \"MCP_PROTOCOL_ERROR\", result);\n }\n return result.tools;\n }\n\n async toolsCall(name: string, args: unknown): Promise<unknown> {\n return this.request(\"tools/call\", { name, arguments: args ?? {} });\n }\n\n async request(method: string, params?: unknown): Promise<unknown> {\n const response = await this.sendRaw({\n jsonrpc: \"2.0\",\n id: this.nextId++,\n method,\n params,\n });\n if (!response) {\n return undefined;\n }\n if (\"error\" in response) {\n throw new McpRpcError(response.error.message, \"MCP_ERROR\", response.error);\n }\n return response.result;\n }\n\n async sendRaw(request: JsonRpcRequest): Promise<JsonRpcResponse | undefined> {\n const token = await this.options.tokenProvider?.getAccessToken();\n let response = await this.postJson(request, token);\n if (response.status === 401 && this.options.tokenProvider) {\n const refreshed = await this.options.tokenProvider.refreshAfterUnauthorized();\n if (refreshed) {\n response = await this.postJson(request, refreshed);\n }\n }\n\n if (response.status === 204 || response.status === 202) {\n return undefined;\n }\n const text = await response.text();\n if (!response.ok) {\n throw new McpRpcError(\n `MCP HTTP request failed with HTTP ${response.status}.`,\n \"MCP_HTTP_ERROR\",\n httpErrorDetails(response.status, text, this.options.envVars ?? process.env),\n );\n }\n if (!text.trim()) {\n return undefined;\n }\n const parsed = JSON.parse(text) as unknown;\n if (!isJsonRpcResponse(parsed)) {\n throw new McpRpcError(\"MCP response was not a JSON-RPC response.\", \"MCP_PROTOCOL_ERROR\", parsed);\n }\n return parsed;\n }\n\n private postJson(request: JsonRpcRequest, token: string | undefined): Promise<Response> {\n const headers: Record<string, string> = {\n \"content-type\": \"application/json\",\n accept: \"application/json\",\n };\n if (token) {\n headers.authorization = `Bearer ${token}`;\n }\n return this.fetchImpl(this.options.endpoint, {\n method: \"POST\",\n headers,\n body: JSON.stringify(request),\n });\n }\n}\n\nfunction isJsonRpcResponse(value: unknown): value is JsonRpcResponse {\n return isRecord(value)\n && value.jsonrpc === \"2.0\"\n && (\"result\" in value || \"error\" in value);\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction httpErrorDetails(status: number, body: string, envVars: NodeJS.ProcessEnv): Record<string, unknown> {\n const details: Record<string, unknown> = { status };\n if (envVars.AINECTO_CLI_DEBUG === \"1\" || envVars.AINECTO_DEBUG === \"1\") {\n details.body = safeBodyPreview(body);\n }\n return details;\n}\n\nexport function safeBodyPreview(body: string): string {\n return body.length > 500 ? `${body.slice(0, 500)}...` : body;\n}\n","import { createInterface } from \"node:readline\";\nimport type { Readable, Writable } from \"node:stream\";\nimport { McpRpcClient, type JsonRpcRequest } from \"./rpcClient\";\n\nexport interface StdioBridgeOptions {\n input: Readable;\n output: Writable;\n errorOutput: Writable;\n client: McpRpcClient;\n}\n\nexport async function runStdioBridge(options: StdioBridgeOptions): Promise<void> {\n const lines = createInterface({ input: options.input, crlfDelay: Infinity });\n\n for await (const line of lines) {\n if (!line.trim()) {\n continue;\n }\n try {\n const request = parseJsonRpcRequest(line);\n const response = await options.client.sendRaw(request);\n if (response && request.id !== undefined) {\n options.output.write(`${JSON.stringify(response)}\\n`);\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n options.output.write(`${JSON.stringify({\n jsonrpc: \"2.0\",\n id: null,\n error: { code: -32603, message },\n })}\\n`);\n }\n }\n}\n\nfunction parseJsonRpcRequest(line: string): JsonRpcRequest {\n const parsed = JSON.parse(line) as unknown;\n if (!isRecord(parsed) || parsed.jsonrpc !== \"2.0\" || typeof parsed.method !== \"string\") {\n throw new Error(\"Invalid JSON-RPC request.\");\n }\n return {\n jsonrpc: \"2.0\",\n id: typeof parsed.id === \"string\" || typeof parsed.id === \"number\" || parsed.id === null ? parsed.id : undefined,\n method: parsed.method,\n params: parsed.params,\n };\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n","import { FileTokenStore } from \"../../core/auth/tokenStore\";\nimport { OAuthClient } from \"../../core/auth/oauth\";\nimport { McpRpcClient } from \"../../core/mcp/rpcClient\";\nimport { runStdioBridge } from \"../../core/mcp/stdioBridge\";\nimport type { Readable, Writable } from \"node:stream\";\n\nexport interface ConnectorOptions {\n endpoint: string;\n input: Readable;\n output: Writable;\n errorOutput: Writable;\n}\n\nexport async function runConnector(options: ConnectorOptions): Promise<void> {\n const tokenStore = new FileTokenStore();\n const auth = new OAuthClient({ endpoint: options.endpoint, tokenStore });\n const client = new McpRpcClient({ endpoint: options.endpoint, tokenProvider: auth });\n await runStdioBridge({\n input: options.input,\n output: options.output,\n errorOutput: options.errorOutput,\n client,\n });\n}\n","export interface CliErrorShape {\n ok: false;\n error: {\n code: string;\n message: string;\n details?: unknown;\n };\n}\n\nexport interface CliSuccessShape {\n ok: true;\n data: unknown;\n warnings?: string[];\n}\n\nexport function renderSuccess(data: unknown, options: { json?: boolean; warnings?: string[] } = {}): string {\n if (options.json) {\n const shape: CliSuccessShape = { ok: true, data };\n if (options.warnings?.length) {\n shape.warnings = options.warnings;\n }\n return `${JSON.stringify(shape, null, 2)}\\n`;\n }\n const warnings = options.warnings?.length ? `${options.warnings.map((warning) => `Warning: ${warning}`).join(\"\\n\")}\\n` : \"\";\n return `${warnings}${renderHuman(data)}\\n`;\n}\n\nexport function renderError(error: unknown, options: { json?: boolean } = {}): string {\n const shape = toErrorShape(error);\n if (options.json) {\n return `${JSON.stringify(shape, null, 2)}\\n`;\n }\n return `Error: ${shape.error.message}\\n`;\n}\n\nexport function toErrorShape(error: unknown): CliErrorShape {\n if (error instanceof Error) {\n const maybe = error as Error & { code?: string; details?: unknown };\n return {\n ok: false,\n error: {\n code: maybe.code ?? \"CLI_ERROR\",\n message: error.message,\n details: redactSecrets(maybe.details),\n },\n };\n }\n return { ok: false, error: { code: \"CLI_ERROR\", message: String(error) } };\n}\n\nexport function redactSecrets(value: unknown): unknown {\n return redactSecretsInner(value, new WeakSet<object>());\n}\n\nfunction renderHuman(data: unknown): string {\n if (Array.isArray(data)) {\n return data.map((item) => renderHuman(item)).join(\"\\n\");\n }\n if (typeof data === \"string\") {\n return data;\n }\n return JSON.stringify(data, null, 2);\n}\n\nfunction redactSecretsInner(value: unknown, seen: WeakSet<object>): unknown {\n if (typeof value === \"string\") {\n return redactSecretString(value);\n }\n if (Array.isArray(value)) {\n return value.map((item) => redactSecretsInner(item, seen));\n }\n if (value && typeof value === \"object\") {\n if (seen.has(value)) {\n return \"[circular]\";\n }\n seen.add(value);\n const output: Record<string, unknown> = {};\n for (const [key, child] of Object.entries(value)) {\n output[key] = isSecretKey(key) ? \"[redacted]\" : redactSecretsInner(child, seen);\n }\n return output;\n }\n return value;\n}\n\nfunction isSecretKey(key: string): boolean {\n const normalized = key.toLowerCase().replace(/-/g, \"_\");\n return normalized === \"authorization\"\n || normalized.includes(\"access_token\")\n || normalized.includes(\"refresh_token\")\n || normalized.includes(\"client_secret\")\n || normalized.includes(\"token\");\n}\n\nfunction redactSecretString(value: string): string {\n return value\n .replace(/(\"(?:authorization|access_token|refresh_token|client_secret|token)\"\\s*:\\s*\")([^\"]*)(\")/gi, \"$1[redacted]$3\")\n .replace(/((?:authorization|access_token|refresh_token|client_secret|token)=)([^&\\s\"']+)/gi, \"$1[redacted]\")\n .replace(/(authorization:\\s*bearer\\s+)([^\\s,}]+)/gi, \"$1[redacted]\")\n .replace(/(bearer\\s+)(eyJ[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+)/gi, \"$1[redacted]\");\n}\n","import { assertEnv, type AinectoEnv } from \"../../core/config/endpoints\";\n\nexport interface McpBinArgs {\n env?: AinectoEnv;\n endpoint?: string;\n help: boolean;\n}\n\nexport function parseMcpArgs(argv: string[]): McpBinArgs {\n const result: McpBinArgs = { help: false };\n for (let index = 0; index < argv.length; index += 1) {\n const arg = argv[index];\n if (!arg) {\n continue;\n }\n if (arg === \"--env\") {\n result.env = assertEnv(requireFlagValue(arg, argv[++index]));\n } else if (arg === \"--endpoint\") {\n result.endpoint = requireFlagValue(arg, argv[++index]);\n } else if (arg === \"--help\" || arg === \"-h\") {\n result.help = true;\n } else {\n throw new Error(`Unknown argument: ${arg}`);\n }\n }\n return result;\n}\n\nfunction requireFlagValue(flag: string, value: string | undefined): string {\n if (!value || value.startsWith(\"--\")) {\n throw new Error(`${flag} requires a value.`);\n }\n return value;\n}\n","#!/usr/bin/env node\nimport { resolveEndpoint } from \"../core/config/endpoints\";\nimport { runConnector } from \"../adapters/mcp/connector\";\nimport { renderError } from \"../core/output/render\";\nimport { parseMcpArgs } from \"../adapters/mcp/args\";\n\ntry {\n const args = parseMcpArgs(process.argv.slice(2));\n if (args.help) {\n process.stdout.write(\"Usage: mcp [--env prod|dev] [--endpoint URL]\\n\");\n process.exit(0);\n }\n const resolved = resolveEndpoint({ env: args.env, endpoint: args.endpoint });\n await runConnector({\n endpoint: resolved.endpoint,\n input: process.stdin,\n output: process.stdout,\n errorOutput: process.stderr,\n });\n} catch (error) {\n process.stderr.write(renderError(error));\n process.exitCode = 1;\n}\n"],"mappings":"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","names":["createHash","createHash","isRecord","isRecord"]}
1
+ {"version":3,"sources":["../../src/core/config/endpoints.ts","../../src/core/auth/tokenStore.ts","../../src/core/auth/oauth.ts","../../src/core/auth/clientRegistration.ts","../../src/core/harness/role.ts","../../src/core/mcp/rpcClient.ts","../../src/core/mcp/stdioBridge.ts","../../src/adapters/mcp/connector.ts","../../src/core/output/render.ts","../../src/adapters/mcp/args.ts","../../src/bin/mcp.ts"],"sourcesContent":["export type AinectoEnv = \"prod\" | \"dev\";\n\nexport interface EndpointResolutionInput {\n env?: AinectoEnv;\n endpoint?: string;\n envVars?: NodeJS.ProcessEnv;\n}\n\nexport interface ResolvedEndpoint {\n env: AinectoEnv;\n endpoint: string;\n source: \"flag\" | \"env\" | \"default\";\n}\n\n/**\n * 기본 MCP 엔드포인트.\n *\n * ★2026-09-21 도메인 전환으로 ai-erd.com 이 «사람이 보는 주소»가 됐고, /mcp 는 두 도메인\n * 모두에서 동일하게 서빙된다(둘 다 같은 인스턴스). 그래서 기본값을 새 도메인으로 옮긴다.\n *\n * ⚠단, OAuth 메타데이터는 아직 ainecto.com 을 가리킨다:\n * WWW-Authenticate resource_metadata=https://ainecto.com/.well-known/oauth-protected-resource/mcp\n * protected-resource resource=https://ainecto.com/mcp · authorization_servers=[https://ainecto.com]\n * authorization-server issuer=https://ainecto.com\n * issuer 는 «발급자 이름»이라 바꾸면 기존 토큰이 전부 무효가 되어 동결돼 있다(전환 계획서 §4-1).\n *\n * 이 CLI 는 issuer/resource 를 요청 호스트와 «대조하지 않고» 서버가 준 메타데이터를 그대로\n * 따라가므로 영향이 없다. ⚠엄격하게 대조하는 다른 MCP 클라이언트는 resource 불일치를\n * 문제 삼을 수 있다 — 그때는 --endpoint 나 AINECTO_MCP_ENDPOINT 로 옛 주소를 쓸 수 있다.\n *\n * 옛 주소도 계속 동작한다. 끊지 않는다.\n */\nconst DEFAULT_ENDPOINTS: Record<AinectoEnv, string> = {\n prod: \"https://ai-erd.com/mcp\",\n dev: \"https://dev.ai-erd.com/mcp\",\n};\n\n/** 옛 기본값 — 이미 설정에 적어둔 사용자가 있다. isDefaultEndpoint 가 이것도 «기본»으로 본다. */\nconst LEGACY_DEFAULT_ENDPOINTS: readonly string[] = [\n \"https://ainecto.com/mcp\",\n \"https://dev.ainecto.com/mcp\",\n];\n\nexport function resolveEndpoint(input: EndpointResolutionInput = {}): ResolvedEndpoint {\n const envVars = input.envVars ?? process.env;\n const env = input.env ?? \"prod\";\n\n if (input.endpoint) {\n return { env, endpoint: normalizeEndpoint(input.endpoint), source: \"flag\" };\n }\n\n if (envVars.AINECTO_MCP_ENDPOINT) {\n return { env, endpoint: normalizeEndpoint(envVars.AINECTO_MCP_ENDPOINT), source: \"env\" };\n }\n\n return { env, endpoint: DEFAULT_ENDPOINTS[env], source: \"default\" };\n}\n\nexport function normalizeEndpoint(endpoint: string): string {\n const url = new URL(endpoint);\n assertTrustedEndpointUrl(url, \"MCP endpoint\");\n url.hash = \"\";\n return url.toString().replace(/\\/$/, \"\");\n}\n\n/**\n * ★<b>이 env 의 기본 주소와 «정확히» 같은가.</b>\n *\n * <p>{@link isDefaultEndpoint} 는 prod·dev·옛 주소를 전부 «기본»으로 보는 넓은 판정이라,\n * 「env=prod 인데 endpoint 만 dev」 같은 입력을 기본으로 착각한다. 그 판정으로 설정에서\n * {@code --endpoint} 를 빼면, 조회한 주소와 세션이 붙는 주소가 갈라진다\n * (2026-09-23 독립 재리뷰 I7).\n */\nexport function isDefaultEndpointFor(env: AinectoEnv, endpoint: string): boolean {\n return normalizeEndpoint(endpoint) === DEFAULT_ENDPOINTS[env];\n}\n\nexport function isDefaultEndpoint(endpoint: string): boolean {\n const normalized = normalizeEndpoint(endpoint);\n return Object.values(DEFAULT_ENDPOINTS).includes(normalized)\n || LEGACY_DEFAULT_ENDPOINTS.includes(normalized);\n}\n\nexport function assertTrustedEndpointUrl(value: string | URL, label = \"URL\"): void {\n const url = typeof value === \"string\" ? new URL(value) : value;\n if (url.protocol === \"https:\") {\n return;\n }\n if (url.protocol === \"http:\" && isLoopbackHostname(url.hostname)) {\n return;\n }\n throw new Error(`${label} must use https, except http is allowed for localhost loopback endpoints.`);\n}\n\nexport function assertLoopbackRedirectUrl(value: string): void {\n const url = new URL(value);\n if (url.protocol === \"http:\" && isLoopbackHostname(url.hostname)) {\n return;\n }\n throw new Error(\"OAuth redirect URI must be an http localhost loopback URL.\");\n}\n\nfunction isLoopbackHostname(hostname: string): boolean {\n return hostname === \"localhost\"\n || hostname === \"127.0.0.1\"\n || hostname === \"::1\"\n || hostname === \"[::1]\";\n}\n\nexport function assertEnv(value: string | undefined): AinectoEnv | undefined {\n if (value === undefined) {\n return undefined;\n }\n if (value === \"prod\" || value === \"dev\") {\n return value;\n }\n throw new Error(`Invalid --env value \"${value}\". Expected \"prod\" or \"dev\".`);\n}\n","import { createHash } from \"node:crypto\";\nimport { mkdir, readFile, rename, rm, stat, writeFile, chmod } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\n\nexport interface StoredTokenSet {\n endpoint: string;\n accessToken: string;\n refreshToken?: string;\n tokenType?: string;\n expiresAt?: number;\n scope?: string;\n clientId?: string;\n clientSecret?: string;\n authorizationServer?: string;\n updatedAt: string;\n}\n\nexport interface TokenStore {\n load(endpoint: string, role?: string): Promise<StoredTokenSet | undefined>;\n save(endpoint: string, token: StoredTokenSet, role?: string): Promise<void>;\n delete(endpoint: string, role?: string): Promise<void>;\n}\n\ntype TokenFile = Record<string, StoredTokenSet>;\n\nexport class FileTokenStore implements TokenStore {\n readonly filePath: string;\n\n constructor(rootDir = join(homedir(), \".ainecto\")) {\n this.filePath = join(rootDir, \"tokens.json\");\n }\n\n async load(endpoint: string, role?: string): Promise<StoredTokenSet | undefined> {\n const file = await this.readFile();\n return file[tokenKey(endpoint, role)];\n }\n\n async save(endpoint: string, token: StoredTokenSet, role?: string): Promise<void> {\n const file = await this.readFile();\n file[tokenKey(endpoint, role)] = { ...token, endpoint, updatedAt: new Date().toISOString() };\n await this.writeFile(file);\n }\n\n async delete(endpoint: string, role?: string): Promise<void> {\n const file = await this.readFile();\n delete file[tokenKey(endpoint, role)];\n await this.writeFile(file);\n }\n\n private async readFile(): Promise<TokenFile> {\n try {\n await this.hardenExistingPermissions();\n const raw = await readFile(this.filePath, \"utf8\");\n const parsed = JSON.parse(raw) as unknown;\n if (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n throw new Error(\"Token file must contain an object.\");\n }\n return parsed as TokenFile;\n } catch (error) {\n if (isNodeError(error, \"ENOENT\")) {\n return {};\n }\n throw error;\n }\n }\n\n private async writeFile(file: TokenFile): Promise<void> {\n await mkdir(dirname(this.filePath), { recursive: true, mode: 0o700 });\n await chmod(dirname(this.filePath), 0o700);\n const tmpPath = `${this.filePath}.${process.pid}.${Date.now()}.tmp`;\n await writeFile(tmpPath, `${JSON.stringify(file, null, 2)}\\n`, { mode: 0o600 });\n await chmod(tmpPath, 0o600);\n await rename(tmpPath, this.filePath);\n await chmod(this.filePath, 0o600);\n }\n\n private async hardenExistingPermissions(): Promise<void> {\n const dirPath = dirname(this.filePath);\n await chmodIfPermissive(dirPath, 0o700);\n await chmodIfPermissive(this.filePath, 0o600);\n }\n}\n\n/**\n * ★역할마다 토큰을 «따로» 둔다.\n *\n * <p>하나로 두면 design 세션으로 로그인하는 순간 development 세션의 토큰이 덮여, 돌고 있던\n * 세션의 역할이 몰래 바뀐다. 역할이 토큰에 박히는 설계에서 토큰 저장소가 한 칸이면 그 칸이\n * 곧 역할 전환 스위치가 된다.\n *\n * <p>역할이 없으면 종전 키 그대로다 — 이미 로그인해 둔 사람이 다시 로그인하지 않아도 된다.\n */\nexport function tokenKey(endpoint: string, role?: string): string {\n const material = role && role.trim() ? `${endpoint}#role=${role.trim().toLowerCase()}` : endpoint;\n return createHash(\"sha256\").update(material).digest(\"hex\");\n}\n\nexport async function tokenStorePermissions(path: string): Promise<{ mode: number } | undefined> {\n try {\n const result = await stat(path);\n return { mode: result.mode & 0o777 };\n } catch (error) {\n if (isNodeError(error, \"ENOENT\")) {\n return undefined;\n }\n throw error;\n }\n}\n\nexport async function tokenStoreDirectoryPermissions(path: string): Promise<{ mode: number } | undefined> {\n return tokenStorePermissions(dirname(path));\n}\n\nexport async function removeTokenStoreForTests(path: string): Promise<void> {\n await rm(dirname(path), { recursive: true, force: true });\n}\n\nfunction isNodeError(error: unknown, code: string): error is NodeJS.ErrnoException {\n return error instanceof Error && \"code\" in error && error.code === code;\n}\n\nasync function chmodIfPermissive(path: string, mode: number): Promise<void> {\n try {\n const result = await stat(path);\n if ((result.mode & 0o077) !== 0) {\n await chmod(path, mode);\n }\n } catch (error) {\n if (isNodeError(error, \"ENOENT\")) {\n return;\n }\n throw error;\n }\n}\n","import { createHash, randomBytes } from \"node:crypto\";\nimport { createServer } from \"node:http\";\nimport { spawn } from \"node:child_process\";\nimport { URLSearchParams } from \"node:url\";\nimport type { StoredTokenSet, TokenStore } from \"./tokenStore\";\nimport { registerPublicClient, type ClientRegistrationResult } from \"./clientRegistration\";\nimport { assertTrustedEndpointUrl, isDefaultEndpoint } from \"../config/endpoints\";\nimport { ROLE_SCOPE_PREFIX, type HarnessRole } from \"../harness/role\";\n\nexport interface OAuthClientOptions {\n /** 이 클라이언트가 쓰는 세션 역할. 토큰이 이 역할로 발급되고 저장된다. */\n role?: HarnessRole;\n endpoint: string;\n tokenStore: TokenStore;\n fetchImpl?: typeof fetch;\n envVars?: NodeJS.ProcessEnv;\n openBrowser?: (url: string) => Promise<void>;\n}\n\nexport interface OAuthMetadata {\n authorizationEndpoint: string;\n tokenEndpoint: string;\n registrationEndpoint?: string;\n issuer?: string;\n codeChallengeMethodsSupported: string[];\n}\n\nexport interface TokenProvider {\n getAccessToken(): Promise<string | undefined>;\n refreshAfterUnauthorized(): Promise<string | undefined>;\n}\n\nexport class OAuthClient implements TokenProvider {\n private readonly fetchImpl: typeof fetch;\n private readonly envVars: NodeJS.ProcessEnv;\n private readonly openBrowserImpl: (url: string) => Promise<void>;\n\n constructor(private readonly options: OAuthClientOptions) {\n this.fetchImpl = options.fetchImpl ?? fetch;\n this.envVars = options.envVars ?? process.env;\n this.openBrowserImpl = options.openBrowser ?? openBrowser;\n }\n\n async getAccessToken(): Promise<string | undefined> {\n const envToken = this.envVars.AINECTO_TOKEN;\n if (envToken) {\n assertEnvTokenEndpointAllowed(this.options.endpoint, this.envVars);\n return envToken;\n }\n\n const stored = await this.options.tokenStore.load(this.options.endpoint, this.options.role);\n if (!stored) {\n return undefined;\n }\n\n if (!shouldRefresh(stored)) {\n return stored.accessToken;\n }\n\n return this.refreshStoredToken(stored);\n }\n\n async refreshAfterUnauthorized(): Promise<string | undefined> {\n const stored = await this.options.tokenStore.load(this.options.endpoint, this.options.role);\n if (!stored?.refreshToken) {\n return undefined;\n }\n return this.refreshStoredToken(stored);\n }\n\n async login(): Promise<StoredTokenSet> {\n const pkce = generatePkcePair();\n const state = generateOAuthState();\n const loopback = await createLoopbackReceiver(state);\n\n try {\n const metadata = await discoverOAuthMetadata(this.options.endpoint, this.fetchImpl);\n const registration = metadata.registrationEndpoint\n ? await registerPublicClient(metadata.registrationEndpoint, loopback.redirectUri, this.fetchImpl)\n : { clientId: \"ainecto-cli\" };\n const authorizeUrl = new URL(metadata.authorizationEndpoint);\n authorizeUrl.searchParams.set(\"response_type\", \"code\");\n authorizeUrl.searchParams.set(\"client_id\", registration.clientId);\n authorizeUrl.searchParams.set(\"redirect_uri\", loopback.redirectUri);\n authorizeUrl.searchParams.set(\"code_challenge\", pkce.codeChallenge);\n authorizeUrl.searchParams.set(\"code_challenge_method\", \"S256\");\n authorizeUrl.searchParams.set(\"resource\", this.options.endpoint);\n authorizeUrl.searchParams.set(\"state\", state);\n // ★역할을 OAuth scope 로 요구한다. 승인은 브라우저에서 사람이 한다 —\n // 그래서 에이전트가 자기 역할을 넓힌 토큰을 혼자 만들 수 없다.\n if (this.options.role) {\n authorizeUrl.searchParams.set(\"scope\", `mcp ${ROLE_SCOPE_PREFIX}${this.options.role}`);\n }\n\n assertTrustedEndpointUrl(authorizeUrl, \"OAuth authorization URL\");\n await this.openBrowserImpl(authorizeUrl.toString());\n const code = await loopback.waitForCode();\n const token = await exchangeToken(metadata.tokenEndpoint, {\n grant_type: \"authorization_code\",\n code,\n redirect_uri: loopback.redirectUri,\n client_id: registration.clientId,\n code_verifier: pkce.codeVerifier,\n resource: this.options.endpoint,\n ...(registration.clientSecret ? { client_secret: registration.clientSecret } : {}),\n }, this.fetchImpl);\n\n const stored = toStoredToken(this.options.endpoint, token, metadata, registration);\n await this.options.tokenStore.save(this.options.endpoint, stored, this.options.role);\n return stored;\n } finally {\n await loopback.close();\n }\n }\n\n async logout(): Promise<void> {\n await this.options.tokenStore.delete(this.options.endpoint, this.options.role);\n }\n\n private async refreshStoredToken(stored: StoredTokenSet): Promise<string | undefined> {\n if (!stored.refreshToken) {\n return stored.accessToken;\n }\n const metadata = await discoverOAuthMetadata(this.options.endpoint, this.fetchImpl);\n const token = await exchangeToken(metadata.tokenEndpoint, {\n grant_type: \"refresh_token\",\n refresh_token: stored.refreshToken,\n client_id: stored.clientId ?? \"ainecto-cli\",\n ...(stored.clientSecret ? { client_secret: stored.clientSecret } : {}),\n resource: this.options.endpoint,\n }, this.fetchImpl);\n const next = toStoredToken(this.options.endpoint, token, metadata, stored);\n await this.options.tokenStore.save(this.options.endpoint, next, this.options.role);\n return next.accessToken;\n }\n}\n\nexport function generatePkcePair(): { codeVerifier: string; codeChallenge: string } {\n const codeVerifier = randomBytes(32).toString(\"base64url\");\n const codeChallenge = createHash(\"sha256\").update(codeVerifier).digest(\"base64url\");\n return { codeVerifier, codeChallenge };\n}\n\nexport function generateOAuthState(): string {\n return randomBytes(32).toString(\"base64url\");\n}\n\nexport function shouldRefresh(token: Pick<StoredTokenSet, \"expiresAt\">, now = Date.now()): boolean {\n if (!token.expiresAt) {\n return false;\n }\n return token.expiresAt - now < 60_000;\n}\n\nexport async function discoverOAuthMetadata(endpoint: string, fetchImpl: typeof fetch = fetch): Promise<OAuthMetadata> {\n assertTrustedEndpointUrl(endpoint, \"MCP endpoint\");\n const resourceMetadataUrl = await discoverResourceMetadataUrl(endpoint, fetchImpl);\n assertTrustedEndpointUrl(resourceMetadataUrl, \"OAuth protected resource metadata URL\");\n const resourceMetadata = await fetchJson<Record<string, unknown>>(resourceMetadataUrl, fetchImpl);\n const authorizationServers = resourceMetadata.authorization_servers;\n if (!Array.isArray(authorizationServers) || typeof authorizationServers[0] !== \"string\") {\n throw new Error(\"OAuth protected resource metadata did not include authorization_servers.\");\n }\n const authServer = authorizationServers[0];\n assertTrustedEndpointUrl(authServer, \"OAuth authorization server\");\n const metadataUrl = authServer.includes(\"/.well-known/\")\n ? authServer\n : `${authServer.replace(/\\/$/, \"\")}/.well-known/oauth-authorization-server`;\n assertTrustedEndpointUrl(metadataUrl, \"OAuth authorization server metadata URL\");\n const metadata = await fetchJson<Record<string, unknown>>(metadataUrl, fetchImpl);\n if (typeof metadata.authorization_endpoint !== \"string\" || typeof metadata.token_endpoint !== \"string\") {\n throw new Error(\"OAuth authorization server metadata is missing authorization_endpoint or token_endpoint.\");\n }\n assertTrustedEndpointUrl(metadata.authorization_endpoint, \"OAuth authorization endpoint\");\n assertTrustedEndpointUrl(metadata.token_endpoint, \"OAuth token endpoint\");\n if (typeof metadata.registration_endpoint === \"string\") {\n assertTrustedEndpointUrl(metadata.registration_endpoint, \"OAuth client registration endpoint\");\n }\n if (typeof metadata.issuer === \"string\") {\n assertTrustedEndpointUrl(metadata.issuer, \"OAuth issuer\");\n }\n const codeChallengeMethodsSupported = parseStringArray(metadata.code_challenge_methods_supported);\n if (!codeChallengeMethodsSupported.includes(\"S256\")) {\n throw new Error(\"OAuth authorization server metadata must support PKCE S256.\");\n }\n return {\n authorizationEndpoint: metadata.authorization_endpoint,\n tokenEndpoint: metadata.token_endpoint,\n registrationEndpoint: typeof metadata.registration_endpoint === \"string\" ? metadata.registration_endpoint : undefined,\n issuer: typeof metadata.issuer === \"string\" ? metadata.issuer : undefined,\n codeChallengeMethodsSupported,\n };\n}\n\nasync function discoverResourceMetadataUrl(endpoint: string, fetchImpl: typeof fetch): Promise<string> {\n const challengeUrl = new URL(endpoint);\n assertTrustedEndpointUrl(challengeUrl, \"MCP endpoint\");\n const response = await fetchImpl(challengeUrl, { method: \"GET\" });\n const challenge = response.headers.get(\"www-authenticate\");\n const fromChallenge = challenge ? parseBearerChallengeParam(challenge, \"resource_metadata\") : undefined;\n if (fromChallenge) {\n assertTrustedEndpointUrl(fromChallenge, \"OAuth protected resource metadata URL\");\n return fromChallenge;\n }\n const origin = new URL(endpoint).origin;\n const fallback = `${origin}/.well-known/oauth-protected-resource`;\n assertTrustedEndpointUrl(fallback, \"OAuth protected resource metadata URL\");\n return fallback;\n}\n\nexport function parseBearerChallengeParam(header: string, name: string): string | undefined {\n const pattern = new RegExp(`${name}=\"([^\"]+)\"`);\n return pattern.exec(header)?.[1];\n}\n\nasync function exchangeToken(\n tokenEndpoint: string,\n params: Record<string, string>,\n fetchImpl: typeof fetch,\n): Promise<Record<string, unknown>> {\n assertTrustedEndpointUrl(tokenEndpoint, \"OAuth token endpoint\");\n const response = await fetchImpl(tokenEndpoint, {\n method: \"POST\",\n headers: { \"content-type\": \"application/x-www-form-urlencoded\" },\n body: new URLSearchParams(params),\n });\n if (!response.ok) {\n throw new Error(`OAuth token exchange failed with HTTP ${response.status}.`);\n }\n return response.json() as Promise<Record<string, unknown>>;\n}\n\ntype TokenContext = Partial<Pick<StoredTokenSet, \"refreshToken\" | \"tokenType\" | \"expiresAt\" | \"scope\" | \"clientId\" | \"clientSecret\">>\n & Partial<ClientRegistrationResult>;\n\nfunction toStoredToken(\n endpoint: string,\n token: Record<string, unknown>,\n metadata: OAuthMetadata,\n previous?: TokenContext,\n): StoredTokenSet {\n if (typeof token.access_token !== \"string\") {\n throw new Error(\"OAuth token response did not include access_token.\");\n }\n const expiresIn = typeof token.expires_in === \"number\" ? token.expires_in : undefined;\n return {\n endpoint,\n accessToken: token.access_token,\n refreshToken: typeof token.refresh_token === \"string\" ? token.refresh_token : previous?.refreshToken,\n tokenType: typeof token.token_type === \"string\" ? token.token_type : previous?.tokenType,\n expiresAt: expiresIn ? Date.now() + expiresIn * 1000 : previous?.expiresAt,\n scope: typeof token.scope === \"string\" ? token.scope : previous?.scope,\n clientId: previous?.clientId ?? \"ainecto-cli\",\n clientSecret: previous?.clientSecret,\n authorizationServer: metadata.issuer,\n updatedAt: new Date().toISOString(),\n };\n}\n\nasync function createLoopbackReceiver(expectedState: string): Promise<{\n redirectUri: string;\n waitForCode(): Promise<string>;\n close(): Promise<void>;\n}> {\n let resolveCode!: (code: string) => void;\n let rejectCode!: (error: Error) => void;\n const codePromise = new Promise<string>((resolve, reject) => {\n resolveCode = resolve;\n rejectCode = reject;\n });\n codePromise.catch(() => undefined);\n\n const server = createServer((req, res) => {\n const url = new URL(req.url ?? \"/\", \"http://127.0.0.1\");\n const error = url.searchParams.get(\"error\");\n const code = url.searchParams.get(\"code\");\n const state = url.searchParams.get(\"state\");\n if (error) {\n res.writeHead(400, { \"content-type\": \"text/plain\" });\n res.end(\"Ainecto CLI authorization failed. You can close this tab.\");\n rejectCode(new Error(`OAuth authorization failed: ${error}`));\n return;\n }\n if (!state || state !== expectedState) {\n res.writeHead(400, { \"content-type\": \"text/plain\" });\n res.end(\"Ainecto CLI authorization state mismatch. You can close this tab.\");\n rejectCode(new Error(\"OAuth state mismatch.\"));\n return;\n }\n if (!code) {\n res.writeHead(400, { \"content-type\": \"text/plain\" });\n res.end(\"Missing OAuth code.\");\n rejectCode(new Error(\"OAuth redirect did not include a code.\"));\n return;\n }\n res.writeHead(200, { \"content-type\": \"text/plain\" });\n res.end(\"Ainecto CLI authorization complete. You can close this tab.\");\n resolveCode(code);\n });\n\n await new Promise<void>((resolve) => server.listen(0, \"127.0.0.1\", resolve));\n const address = server.address();\n if (!address || typeof address === \"string\") {\n throw new Error(\"Loopback OAuth server did not bind to a TCP port.\");\n }\n return {\n redirectUri: `http://127.0.0.1:${address.port}/callback`,\n waitForCode: () => codePromise,\n close: () => new Promise<void>((resolve, reject) => server.close((error) => error ? reject(error) : resolve())),\n };\n}\n\nfunction parseStringArray(value: unknown): string[] {\n return Array.isArray(value) ? value.filter((item): item is string => typeof item === \"string\") : [];\n}\n\nasync function fetchJson<T>(url: string, fetchImpl: typeof fetch): Promise<T> {\n assertTrustedEndpointUrl(url, \"OAuth metadata URL\");\n const response = await fetchImpl(url);\n if (!response.ok) {\n throw new Error(`Failed to fetch OAuth metadata from ${url}: HTTP ${response.status}.`);\n }\n return response.json() as Promise<T>;\n}\n\nexport function getBrowserOpenCommand(\n url: string,\n platform: NodeJS.Platform = process.platform,\n): { command: string; args: string[] } {\n assertTrustedEndpointUrl(url, \"OAuth authorization URL\");\n if (platform === \"darwin\") {\n return { command: \"open\", args: [url] };\n }\n if (platform === \"win32\") {\n return { command: \"explorer.exe\", args: [url] };\n }\n return { command: \"xdg-open\", args: [url] };\n}\n\nasync function openBrowser(url: string): Promise<void> {\n const { command, args } = getBrowserOpenCommand(url);\n const child = spawn(command, args, { stdio: \"ignore\", detached: true });\n child.unref();\n}\n\nfunction assertEnvTokenEndpointAllowed(endpoint: string, envVars: NodeJS.ProcessEnv): void {\n if (envVars.AINECTO_ALLOW_CUSTOM_ENDPOINT_TOKEN === \"1\") {\n return;\n }\n if (isDefaultEndpoint(endpoint)) {\n return;\n }\n throw new Error(\"AINECTO_TOKEN can only be used with the default prod/dev endpoints. Set AINECTO_ALLOW_CUSTOM_ENDPOINT_TOKEN=1 only when you intentionally trust the custom endpoint.\");\n}\n","import { assertLoopbackRedirectUrl, assertTrustedEndpointUrl } from \"../config/endpoints\";\n\nexport interface ClientRegistrationResult {\n clientId: string;\n clientSecret?: string;\n}\n\nexport async function registerPublicClient(\n registrationEndpoint: string,\n redirectUri: string,\n fetchImpl: typeof fetch = fetch,\n): Promise<ClientRegistrationResult> {\n assertTrustedEndpointUrl(registrationEndpoint, \"OAuth client registration endpoint\");\n assertLoopbackRedirectUrl(redirectUri);\n const response = await fetchImpl(registrationEndpoint, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\", accept: \"application/json\" },\n body: JSON.stringify({\n client_name: \"Ainecto CLI\",\n redirect_uris: [redirectUri],\n token_endpoint_auth_method: \"none\",\n grant_types: [\"authorization_code\", \"refresh_token\"],\n response_types: [\"code\"],\n }),\n });\n if (!response.ok) {\n throw new Error(`OAuth client registration failed with HTTP ${response.status}.`);\n }\n const body = await response.json() as unknown;\n if (!isRecord(body) || typeof body.client_id !== \"string\") {\n throw new Error(\"OAuth client registration response did not include client_id.\");\n }\n return {\n clientId: body.client_id,\n clientSecret: typeof body.client_secret === \"string\" ? body.client_secret : undefined,\n };\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n","/**\n * 세션 역할 — AI-ERD Harness 의 「하나의 세션은 하나의 역할만 가진다」를 클라이언트 쪽에서\n * 실어 나르는 부분.\n *\n * ★역할은 «에이전트가 못 바꾸는 곳»에서 와야 한다. 그래서 출처를 둘로만 둔다:\n *\n * ① --role 플래그 MCP 서버 설정의 args 에 사람이 적는다\n * → Claude Code(.mcp.json) · Cursor(.cursor/mcp.json) 처럼\n * «프로젝트별» 설정이 있는 에이전트\n * ② AI_ERD_ROLE 세션을 띄우는 환경변수\n * → Codex 처럼 MCP 설정이 «전역»뿐이라 프로젝트별로 못 나누는 에이전트\n * ★이 브리지 프로세스는 세션 시작 시점에 뜨고 그때의 환경을 물려받는다.\n * 에이전트가 나중에 export 해도 이미 뜬 프로세스에는 닿지 않는다.\n *\n * ⛔«도구로 역할을 선언»하는 길은 택하지 않았다. 에이전트가 스스로 바꿀 수 있으면 제약이\n * 아니다 — 막히는 순간 「역할을 바꿔서 하겠습니다」가 가장 자연스러운 다음 수가 된다.\n *\n * ⚠강제하는 쪽은 서버다. 이 파일은 역할을 «전달»만 한다. 브리지에서 도구를 걸러 봐야\n * 브리지를 안 거치는 연결(HTTP 직결)에는 아무 효과가 없기 때문이다.\n */\n\nexport const HARNESS_ROLES = [\"design\", \"development\", \"test\", \"validation\"] as const;\n\nexport type HarnessRole = (typeof HARNESS_ROLES)[number];\n\n/**\n * ★역할을 싣는 OAuth scope 접두사. 서버의 McpSessionRole.ROLE_SCOPE_PREFIX 와 같아야 한다.\n *\n * <p>이것이 «진짜» 출처다. 아래 헤더는 역할 scope 토큰이 없을 때의 권고일 뿐이고,\n * 같은 토큰을 쥔 다른 경로(셸에서 CLI 직접 호출 등)는 헤더를 안 보낸다.\n */\nexport const ROLE_SCOPE_PREFIX = \"ai-erd:role:\";\n\n/** 서버가 읽는 헤더 이름. 서버의 McpSessionRoleResolver.ROLE_HEADER 와 같아야 한다. */\nexport const ROLE_HEADER = \"X-AI-ERD-Role\";\n\n/** 설정이 전역뿐인 에이전트(Codex 등)를 위한 환경변수. */\nexport const ROLE_ENV_VAR = \"AI_ERD_ROLE\";\n\nexport interface RoleResolutionInput {\n role?: string;\n envVars?: NodeJS.ProcessEnv;\n}\n\nexport interface ResolvedRole {\n role?: HarnessRole;\n source: \"flag\" | \"env\" | \"none\";\n}\n\nexport function resolveRole(input: RoleResolutionInput = {}): ResolvedRole {\n if (input.role !== undefined) {\n return { role: assertRole(input.role), source: \"flag\" };\n }\n const fromEnv = (input.envVars ?? process.env)[ROLE_ENV_VAR];\n if (fromEnv && fromEnv.trim()) {\n return { role: assertRole(fromEnv), source: \"env\" };\n }\n return { source: \"none\" };\n}\n\n/**\n * ⚠여기서는 «틀리면 멈춘다». 서버는 모르는 값을 FULL 로 받아 넘기지만, 그건 남의 설정이\n * 조용히 죽지 않게 하려는 것이고 — 이쪽은 방금 사람이 친 값이라 오타를 알려주는 편이 낫다.\n * 조용히 «역할 없음»으로 도는 것이 이 도구에서 가장 나쁜 실패다.\n */\nexport function assertRole(value: string): HarnessRole {\n const normalized = value.trim().toLowerCase();\n if ((HARNESS_ROLES as readonly string[]).includes(normalized)) {\n return normalized as HarnessRole;\n }\n throw new Error(\n `Invalid role \"${value}\". Expected one of: ${HARNESS_ROLES.join(\", \")}.`,\n );\n}\n\n/** 사람이 읽는 이름. 서버의 거부 안내문과 같은 어휘를 쓴다. */\nexport function roleDisplayName(role: HarnessRole): string {\n return `${role.charAt(0).toUpperCase()}${role.slice(1)} Session`;\n}\n","import type { TokenProvider } from \"../auth/oauth\";\nimport { ROLE_HEADER, type HarnessRole } from \"../harness/role\";\n\nexport interface JsonRpcRequest {\n jsonrpc: \"2.0\";\n id?: string | number | null;\n method: string;\n params?: unknown;\n}\n\nexport interface JsonRpcSuccess {\n jsonrpc: \"2.0\";\n id?: string | number | null;\n result: unknown;\n}\n\nexport interface JsonRpcFailure {\n jsonrpc: \"2.0\";\n id?: string | number | null;\n error: {\n code: number;\n message: string;\n data?: unknown;\n };\n}\n\nexport type JsonRpcResponse = JsonRpcSuccess | JsonRpcFailure;\n\nexport interface McpRpcClientOptions {\n endpoint: string;\n tokenProvider?: TokenProvider;\n fetchImpl?: typeof fetch;\n envVars?: NodeJS.ProcessEnv;\n /** 세션 역할. 있으면 모든 요청에 실린다 — 강제는 서버가 한다. */\n role?: HarnessRole;\n}\n\nexport class McpRpcError extends Error {\n constructor(\n message: string,\n readonly code: string,\n readonly details?: unknown,\n ) {\n super(message);\n }\n}\n\nexport class McpRpcClient {\n private readonly fetchImpl: typeof fetch;\n private nextId = 1;\n\n constructor(private readonly options: McpRpcClientOptions) {\n this.fetchImpl = options.fetchImpl ?? fetch;\n }\n\n initialize(): Promise<unknown> {\n return this.request(\"initialize\", {\n protocolVersion: \"2024-11-05\",\n capabilities: {},\n clientInfo: { name: \"@ainecto/mcp\", version: \"0.1.0\" },\n });\n }\n\n async toolsList(): Promise<unknown[]> {\n const result = await this.request(\"tools/list\", {});\n if (!isRecord(result) || !Array.isArray(result.tools)) {\n throw new McpRpcError(\"tools/list response did not include a tools array.\", \"MCP_PROTOCOL_ERROR\", result);\n }\n return result.tools;\n }\n\n async toolsCall(name: string, args: unknown): Promise<unknown> {\n return this.request(\"tools/call\", { name, arguments: args ?? {} });\n }\n\n async request(method: string, params?: unknown): Promise<unknown> {\n const response = await this.sendRaw({\n jsonrpc: \"2.0\",\n id: this.nextId++,\n method,\n params,\n });\n if (!response) {\n return undefined;\n }\n if (\"error\" in response) {\n throw new McpRpcError(response.error.message, \"MCP_ERROR\", response.error);\n }\n return response.result;\n }\n\n async sendRaw(request: JsonRpcRequest): Promise<JsonRpcResponse | undefined> {\n const token = await this.options.tokenProvider?.getAccessToken();\n let response = await this.postJson(request, token);\n if (response.status === 401 && this.options.tokenProvider) {\n const refreshed = await this.options.tokenProvider.refreshAfterUnauthorized();\n if (refreshed) {\n response = await this.postJson(request, refreshed);\n }\n }\n\n if (response.status === 204 || response.status === 202) {\n return undefined;\n }\n const text = await response.text();\n if (!response.ok) {\n throw new McpRpcError(\n `MCP HTTP request failed with HTTP ${response.status}.`,\n \"MCP_HTTP_ERROR\",\n httpErrorDetails(response.status, text, this.options.envVars ?? process.env),\n );\n }\n if (!text.trim()) {\n return undefined;\n }\n const parsed = JSON.parse(text) as unknown;\n if (!isJsonRpcResponse(parsed)) {\n throw new McpRpcError(\"MCP response was not a JSON-RPC response.\", \"MCP_PROTOCOL_ERROR\", parsed);\n }\n return parsed;\n }\n\n private postJson(request: JsonRpcRequest, token: string | undefined): Promise<Response> {\n const headers: Record<string, string> = {\n \"content-type\": \"application/json\",\n accept: \"application/json\",\n };\n if (token) {\n headers.authorization = `Bearer ${token}`;\n }\n if (this.options.role) {\n headers[ROLE_HEADER.toLowerCase()] = this.options.role;\n }\n return this.fetchImpl(this.options.endpoint, {\n method: \"POST\",\n headers,\n body: JSON.stringify(request),\n });\n }\n}\n\n/**\n * ★MCP 는 «도구가 거부/실패했다»를 JSON-RPC error 가 아니라 결과 안의 {@code isError} 로\n * 알린다(2025-06-18 규격). 그래서 최상위 error 만 보면 실패가 성공으로 보고된다 —\n * 셸 자동화는 exit 0 을 받고 다음 단계로 간다(2026-09-22 독립 리뷰 I9).\n */\nexport function isToolError(result: unknown): boolean {\n return isRecord(result) && result.isError === true;\n}\n\nfunction isJsonRpcResponse(value: unknown): value is JsonRpcResponse {\n return isRecord(value)\n && value.jsonrpc === \"2.0\"\n && (\"result\" in value || \"error\" in value);\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction httpErrorDetails(status: number, body: string, envVars: NodeJS.ProcessEnv): Record<string, unknown> {\n const details: Record<string, unknown> = { status };\n if (envVars.AINECTO_CLI_DEBUG === \"1\" || envVars.AINECTO_DEBUG === \"1\") {\n details.body = safeBodyPreview(body);\n }\n return details;\n}\n\nexport function safeBodyPreview(body: string): string {\n return body.length > 500 ? `${body.slice(0, 500)}...` : body;\n}\n","import { createInterface } from \"node:readline\";\nimport type { Readable, Writable } from \"node:stream\";\nimport { McpRpcClient, type JsonRpcRequest } from \"./rpcClient\";\n\nexport interface StdioBridgeOptions {\n input: Readable;\n output: Writable;\n errorOutput: Writable;\n client: McpRpcClient;\n}\n\nexport async function runStdioBridge(options: StdioBridgeOptions): Promise<void> {\n const lines = createInterface({ input: options.input, crlfDelay: Infinity });\n\n for await (const line of lines) {\n if (!line.trim()) {\n continue;\n }\n try {\n const request = parseJsonRpcRequest(line);\n const response = await options.client.sendRaw(request);\n if (response && request.id !== undefined) {\n options.output.write(`${JSON.stringify(response)}\\n`);\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n options.output.write(`${JSON.stringify({\n jsonrpc: \"2.0\",\n id: null,\n error: { code: -32603, message },\n })}\\n`);\n }\n }\n}\n\nfunction parseJsonRpcRequest(line: string): JsonRpcRequest {\n const parsed = JSON.parse(line) as unknown;\n if (!isRecord(parsed) || parsed.jsonrpc !== \"2.0\" || typeof parsed.method !== \"string\") {\n throw new Error(\"Invalid JSON-RPC request.\");\n }\n return {\n jsonrpc: \"2.0\",\n id: typeof parsed.id === \"string\" || typeof parsed.id === \"number\" || parsed.id === null ? parsed.id : undefined,\n method: parsed.method,\n params: parsed.params,\n };\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n","import { FileTokenStore } from \"../../core/auth/tokenStore\";\nimport { OAuthClient } from \"../../core/auth/oauth\";\nimport { McpRpcClient } from \"../../core/mcp/rpcClient\";\nimport { runStdioBridge } from \"../../core/mcp/stdioBridge\";\nimport type { HarnessRole } from \"../../core/harness/role\";\nimport type { Readable, Writable } from \"node:stream\";\n\nexport interface ConnectorOptions {\n endpoint: string;\n role?: HarnessRole;\n input: Readable;\n output: Writable;\n errorOutput: Writable;\n}\n\nexport async function runConnector(options: ConnectorOptions): Promise<void> {\n const tokenStore = new FileTokenStore();\n // ★브리지도 «역할별» 토큰을 써야 한다. 여기에 역할을 안 넘기면 역할별로 로그인해 둔\n // 자격증명을 못 찾고, 남아 있는 무역할 토큰을 집는다 — 제한이 조용히 풀린다\n // (2026-09-23 독립 재리뷰 C2. RPC 클라이언트에는 넘기고 여기만 빠뜨렸다).\n const auth = new OAuthClient({ endpoint: options.endpoint, tokenStore, role: options.role });\n const client = new McpRpcClient({\n endpoint: options.endpoint,\n tokenProvider: auth,\n role: options.role,\n });\n await runStdioBridge({\n input: options.input,\n output: options.output,\n errorOutput: options.errorOutput,\n client,\n });\n}\n","export interface CliErrorShape {\n ok: false;\n error: {\n code: string;\n message: string;\n details?: unknown;\n };\n}\n\nexport interface CliSuccessShape {\n ok: true;\n data: unknown;\n warnings?: string[];\n}\n\nexport function renderSuccess(data: unknown, options: { json?: boolean; warnings?: string[] } = {}): string {\n if (options.json) {\n const shape: CliSuccessShape = { ok: true, data };\n if (options.warnings?.length) {\n shape.warnings = options.warnings;\n }\n return `${JSON.stringify(shape, null, 2)}\\n`;\n }\n const warnings = options.warnings?.length ? `${options.warnings.map((warning) => `Warning: ${warning}`).join(\"\\n\")}\\n` : \"\";\n return `${warnings}${renderHuman(data)}\\n`;\n}\n\nexport function renderError(error: unknown, options: { json?: boolean } = {}): string {\n const shape = toErrorShape(error);\n if (options.json) {\n return `${JSON.stringify(shape, null, 2)}\\n`;\n }\n return `Error: ${shape.error.message}\\n`;\n}\n\nexport function toErrorShape(error: unknown): CliErrorShape {\n if (error instanceof Error) {\n const maybe = error as Error & { code?: string; details?: unknown };\n return {\n ok: false,\n error: {\n code: maybe.code ?? \"CLI_ERROR\",\n message: error.message,\n details: redactSecrets(maybe.details),\n },\n };\n }\n return { ok: false, error: { code: \"CLI_ERROR\", message: String(error) } };\n}\n\nexport function redactSecrets(value: unknown): unknown {\n return redactSecretsInner(value, new WeakSet<object>());\n}\n\nfunction renderHuman(data: unknown): string {\n if (Array.isArray(data)) {\n return data.map((item) => renderHuman(item)).join(\"\\n\");\n }\n if (typeof data === \"string\") {\n return data;\n }\n return JSON.stringify(data, null, 2);\n}\n\nfunction redactSecretsInner(value: unknown, seen: WeakSet<object>): unknown {\n if (typeof value === \"string\") {\n return redactSecretString(value);\n }\n if (Array.isArray(value)) {\n return value.map((item) => redactSecretsInner(item, seen));\n }\n if (value && typeof value === \"object\") {\n if (seen.has(value)) {\n return \"[circular]\";\n }\n seen.add(value);\n const output: Record<string, unknown> = {};\n for (const [key, child] of Object.entries(value)) {\n output[key] = isSecretKey(key) ? \"[redacted]\" : redactSecretsInner(child, seen);\n }\n return output;\n }\n return value;\n}\n\nfunction isSecretKey(key: string): boolean {\n const normalized = key.toLowerCase().replace(/-/g, \"_\");\n return normalized === \"authorization\"\n || normalized.includes(\"access_token\")\n || normalized.includes(\"refresh_token\")\n || normalized.includes(\"client_secret\")\n || normalized.includes(\"token\");\n}\n\nfunction redactSecretString(value: string): string {\n return value\n .replace(/(\"(?:authorization|access_token|refresh_token|client_secret|token)\"\\s*:\\s*\")([^\"]*)(\")/gi, \"$1[redacted]$3\")\n .replace(/((?:authorization|access_token|refresh_token|client_secret|token)=)([^&\\s\"']+)/gi, \"$1[redacted]\")\n .replace(/(authorization:\\s*bearer\\s+)([^\\s,}]+)/gi, \"$1[redacted]\")\n .replace(/(bearer\\s+)(eyJ[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+)/gi, \"$1[redacted]\");\n}\n","import { assertEnv, type AinectoEnv } from \"../../core/config/endpoints\";\nimport { assertRole, type HarnessRole } from \"../../core/harness/role\";\n\nexport interface McpBinArgs {\n env?: AinectoEnv;\n endpoint?: string;\n role?: HarnessRole;\n help: boolean;\n}\n\nexport function parseMcpArgs(argv: string[]): McpBinArgs {\n const result: McpBinArgs = { help: false };\n for (let index = 0; index < argv.length; index += 1) {\n const arg = argv[index];\n if (!arg) {\n continue;\n }\n if (arg === \"--env\") {\n result.env = assertEnv(requireFlagValue(arg, argv[++index]));\n } else if (arg === \"--endpoint\") {\n result.endpoint = requireFlagValue(arg, argv[++index]);\n } else if (arg === \"--role\") {\n result.role = assertRole(requireFlagValue(arg, argv[++index]));\n } else if (arg === \"--help\" || arg === \"-h\") {\n result.help = true;\n } else {\n throw new Error(`Unknown argument: ${arg}`);\n }\n }\n return result;\n}\n\nfunction requireFlagValue(flag: string, value: string | undefined): string {\n if (!value || value.startsWith(\"--\")) {\n throw new Error(`${flag} requires a value.`);\n }\n return value;\n}\n","#!/usr/bin/env node\nimport { resolveEndpoint } from \"../core/config/endpoints\";\nimport { runConnector } from \"../adapters/mcp/connector\";\nimport { renderError } from \"../core/output/render\";\nimport { parseMcpArgs } from \"../adapters/mcp/args\";\nimport { resolveRole, HARNESS_ROLES } from \"../core/harness/role\";\n\ntry {\n const args = parseMcpArgs(process.argv.slice(2));\n if (args.help) {\n process.stdout.write(\n `Usage: mcp [--env prod|dev] [--endpoint URL] [--role ${HARNESS_ROLES.join(\"|\")}]\\n`,\n );\n process.exit(0);\n }\n const resolved = resolveEndpoint({ env: args.env, endpoint: args.endpoint });\n // 플래그가 없으면 환경변수 — Codex 처럼 MCP 설정이 전역뿐인 에이전트를 위한 길이다.\n const resolvedRole = resolveRole({ role: args.role });\n await runConnector({\n endpoint: resolved.endpoint,\n role: resolvedRole.role,\n input: process.stdin,\n output: process.stdout,\n errorOutput: process.stderr,\n });\n} catch (error) {\n process.stderr.write(renderError(error));\n process.exitCode = 1;\n}\n"],"mappings":"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","names":["createHash","createHash","isRecord","isRecord","isRecord"]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ainecto/mcp",
3
- "version": "0.1.4",
4
- "description": "Ainecto MCP connector and first-party CLI.",
3
+ "version": "0.3.0",
4
+ "description": "AI-ERD MCP connector and first-party CLI.",
5
5
  "mcpName": "io.github.codelives/ainecto",
6
6
  "type": "module",
7
7
  "private": false,
@@ -17,7 +17,9 @@
17
17
  "bin": {
18
18
  "mcp": "dist/bin/mcp.js",
19
19
  "ainecto-mcp": "dist/bin/mcp.js",
20
- "ainecto": "dist/bin/ainecto.js"
20
+ "ainecto": "dist/bin/ainecto.js",
21
+ "ai-erd": "dist/bin/ainecto.js",
22
+ "ai-erd-mcp": "dist/bin/mcp.js"
21
23
  },
22
24
  "files": [
23
25
  "dist"
@@ -30,7 +32,8 @@
30
32
  "smoke:mcp": "tsx scripts/smoke-mcp.ts",
31
33
  "smoke:attachments": "tsx scripts/smoke-attachment-upload.ts",
32
34
  "catalog:fixture": "vitest run test/catalog.test.ts",
33
- "prepack": "npm run typecheck && npm test && npm run build"
35
+ "prepack": "npm run typecheck && npm test && npm run build",
36
+ "publish:both": "node scripts/publish-both.mjs"
34
37
  },
35
38
  "devDependencies": {
36
39
  "@types/node": "^20.19.8",