@ogygie/mcp 0.10.0 → 0.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/dist/mcp.js +30 -11
  2. package/dist/server.js +30 -11
  3. package/package.json +2 -2
package/dist/mcp.js CHANGED
@@ -823,7 +823,8 @@ function declaredEntries(manifest) {
823
823
  name: feature.name,
824
824
  status: feature.status,
825
825
  folder: owningApp === void 0 ? null : `${owningApp.path}/${feature.folder}`,
826
- specId: feature.name
826
+ specId: feature.name,
827
+ appType: owningApp?.type ?? null
827
828
  });
828
829
  }
829
830
  for (const productPackage of manifest.packages ?? []) {
@@ -832,7 +833,8 @@ function declaredEntries(manifest) {
832
833
  name: productPackage.name,
833
834
  status: productPackage.status,
834
835
  folder: productPackage.path,
835
- specId: productPackage.name
836
+ specId: productPackage.name,
837
+ appType: null
836
838
  });
837
839
  }
838
840
  for (const frameworkPackage of manifest.framework?.packages ?? []) {
@@ -842,7 +844,8 @@ function declaredEntries(manifest) {
842
844
  status: frameworkPackage.status,
843
845
  folder: frameworkPackage.path,
844
846
  // A published npm name is not a spec id: the link is DECLARED.
845
- specId: frameworkPackage.spec === null ? null : specIdOf(frameworkPackage.spec)
847
+ specId: frameworkPackage.spec === null ? null : specIdOf(frameworkPackage.spec),
848
+ appType: null
846
849
  });
847
850
  }
848
851
  return entries;
@@ -1055,6 +1058,7 @@ async function buildReport(deps, entries, target) {
1055
1058
  dependents.set(entry.name, accumulator);
1056
1059
  }
1057
1060
  if (isTest(file.path)) continue;
1061
+ if (entry.appType === "front" || entry.appType === "gateway") continue;
1058
1062
  for (const table of ownedTables) {
1059
1063
  if (!content.includes(`"${table}"`)) continue;
1060
1064
  tableReadersOutsideOwner.push({ table, feature: entry.name, file: filePath });
@@ -1092,7 +1096,7 @@ async function buildReport(deps, entries, target) {
1092
1096
  scope: {
1093
1097
  scannedFolders: scannedFolders.sort(),
1094
1098
  coveredKinds: [...new Set(entries.map((entry) => entry.kind))],
1095
- outOfReach: [...outOfReach, ...outOfReachOf(target)]
1099
+ outOfReach: [...outOfReach, ...outOfReachOf(target, entries)]
1096
1100
  }
1097
1101
  };
1098
1102
  return ImpactReportSchema.parse(report);
@@ -1105,11 +1109,19 @@ function tablesOf(manifest, featureName) {
1105
1109
  const feature = manifest.features.find((candidate) => candidate.name === featureName);
1106
1110
  return feature === void 0 ? [] : dbTableNamesOf(feature);
1107
1111
  }
1108
- function outOfReachOf(target) {
1112
+ function outOfReachOf(target, entries) {
1109
1113
  const limits = [
1110
1114
  "code that no manifest entry declares \u2014 the map is the only chart",
1111
1115
  "anything outside this repo: no network, no npm registry"
1112
1116
  ];
1117
+ const spared = entries.filter(
1118
+ (entry) => entry.appType === "front" || entry.appType === "gateway"
1119
+ );
1120
+ if (spared.length > 0 && target.kind === "feature") {
1121
+ limits.push(
1122
+ `table ownership was NOT checked in ${spared.length} front/gateway entr${spared.length === 1 ? "y" : "ies"} \u2014 that code holds no database client, so a table name there is a query key or a route`
1123
+ );
1124
+ }
1113
1125
  if (target.kind === "framework-package" || target.kind === "package") {
1114
1126
  limits.unshift(
1115
1127
  `consumers of "${target.name}" OUTSIDE this repo \u2014 it is a package, and a published package is imported by projects this analysis cannot see`
@@ -1488,11 +1500,18 @@ function refuse(response, status, error) {
1488
1500
  response.writeHead(status, { "content-type": "application/json" });
1489
1501
  response.end(JSON.stringify(error));
1490
1502
  }
1491
- function isAuthorized(authorization, expected) {
1492
- if (authorization === void 0) return false;
1493
- const [scheme, value] = authorization.split(" ");
1494
- if (scheme?.toLowerCase() !== "bearer" || value === void 0) return false;
1495
- return tokenMatches(expected, value);
1503
+ var SECRET_PATH_PREFIX = "/mcp-";
1504
+ function isAuthorized(authorization, expected, requestPath) {
1505
+ if (authorization !== void 0) {
1506
+ const [scheme, value] = authorization.split(" ");
1507
+ if (scheme?.toLowerCase() === "bearer" && value !== void 0) {
1508
+ if (tokenMatches(expected, value)) return true;
1509
+ }
1510
+ }
1511
+ if (requestPath === void 0) return false;
1512
+ const [pathOnly] = requestPath.split("?");
1513
+ if (pathOnly === void 0 || !pathOnly.startsWith(SECRET_PATH_PREFIX)) return false;
1514
+ return tokenMatches(expected, pathOnly.slice(SECRET_PATH_PREFIX.length));
1496
1515
  }
1497
1516
  async function startHttpTransport(createServerInstance, options) {
1498
1517
  const token = assertUsableToken(options.token);
@@ -1507,7 +1526,7 @@ async function startHttpTransport(createServerInstance, options) {
1507
1526
  await transport.handleRequest(request, response, body);
1508
1527
  };
1509
1528
  const httpServer = createServer((request, response) => {
1510
- if (!isAuthorized(request.headers.authorization, token)) {
1529
+ if (!isAuthorized(request.headers.authorization, token, request.url)) {
1511
1530
  refuse(
1512
1531
  response,
1513
1532
  401,
package/dist/server.js CHANGED
@@ -818,7 +818,8 @@ function declaredEntries(manifest) {
818
818
  name: feature.name,
819
819
  status: feature.status,
820
820
  folder: owningApp === void 0 ? null : `${owningApp.path}/${feature.folder}`,
821
- specId: feature.name
821
+ specId: feature.name,
822
+ appType: owningApp?.type ?? null
822
823
  });
823
824
  }
824
825
  for (const productPackage of manifest.packages ?? []) {
@@ -827,7 +828,8 @@ function declaredEntries(manifest) {
827
828
  name: productPackage.name,
828
829
  status: productPackage.status,
829
830
  folder: productPackage.path,
830
- specId: productPackage.name
831
+ specId: productPackage.name,
832
+ appType: null
831
833
  });
832
834
  }
833
835
  for (const frameworkPackage of manifest.framework?.packages ?? []) {
@@ -837,7 +839,8 @@ function declaredEntries(manifest) {
837
839
  status: frameworkPackage.status,
838
840
  folder: frameworkPackage.path,
839
841
  // A published npm name is not a spec id: the link is DECLARED.
840
- specId: frameworkPackage.spec === null ? null : specIdOf(frameworkPackage.spec)
842
+ specId: frameworkPackage.spec === null ? null : specIdOf(frameworkPackage.spec),
843
+ appType: null
841
844
  });
842
845
  }
843
846
  return entries;
@@ -1050,6 +1053,7 @@ async function buildReport(deps, entries, target) {
1050
1053
  dependents.set(entry.name, accumulator);
1051
1054
  }
1052
1055
  if (isTest(file.path)) continue;
1056
+ if (entry.appType === "front" || entry.appType === "gateway") continue;
1053
1057
  for (const table of ownedTables) {
1054
1058
  if (!content.includes(`"${table}"`)) continue;
1055
1059
  tableReadersOutsideOwner.push({ table, feature: entry.name, file: filePath });
@@ -1087,7 +1091,7 @@ async function buildReport(deps, entries, target) {
1087
1091
  scope: {
1088
1092
  scannedFolders: scannedFolders.sort(),
1089
1093
  coveredKinds: [...new Set(entries.map((entry) => entry.kind))],
1090
- outOfReach: [...outOfReach, ...outOfReachOf(target)]
1094
+ outOfReach: [...outOfReach, ...outOfReachOf(target, entries)]
1091
1095
  }
1092
1096
  };
1093
1097
  return ImpactReportSchema.parse(report);
@@ -1100,11 +1104,19 @@ function tablesOf(manifest, featureName) {
1100
1104
  const feature = manifest.features.find((candidate) => candidate.name === featureName);
1101
1105
  return feature === void 0 ? [] : dbTableNamesOf(feature);
1102
1106
  }
1103
- function outOfReachOf(target) {
1107
+ function outOfReachOf(target, entries) {
1104
1108
  const limits = [
1105
1109
  "code that no manifest entry declares \u2014 the map is the only chart",
1106
1110
  "anything outside this repo: no network, no npm registry"
1107
1111
  ];
1112
+ const spared = entries.filter(
1113
+ (entry) => entry.appType === "front" || entry.appType === "gateway"
1114
+ );
1115
+ if (spared.length > 0 && target.kind === "feature") {
1116
+ limits.push(
1117
+ `table ownership was NOT checked in ${spared.length} front/gateway entr${spared.length === 1 ? "y" : "ies"} \u2014 that code holds no database client, so a table name there is a query key or a route`
1118
+ );
1119
+ }
1108
1120
  if (target.kind === "framework-package" || target.kind === "package") {
1109
1121
  limits.unshift(
1110
1122
  `consumers of "${target.name}" OUTSIDE this repo \u2014 it is a package, and a published package is imported by projects this analysis cannot see`
@@ -1483,11 +1495,18 @@ function refuse(response, status, error) {
1483
1495
  response.writeHead(status, { "content-type": "application/json" });
1484
1496
  response.end(JSON.stringify(error));
1485
1497
  }
1486
- function isAuthorized(authorization, expected) {
1487
- if (authorization === void 0) return false;
1488
- const [scheme, value] = authorization.split(" ");
1489
- if (scheme?.toLowerCase() !== "bearer" || value === void 0) return false;
1490
- return tokenMatches(expected, value);
1498
+ var SECRET_PATH_PREFIX = "/mcp-";
1499
+ function isAuthorized(authorization, expected, requestPath) {
1500
+ if (authorization !== void 0) {
1501
+ const [scheme, value] = authorization.split(" ");
1502
+ if (scheme?.toLowerCase() === "bearer" && value !== void 0) {
1503
+ if (tokenMatches(expected, value)) return true;
1504
+ }
1505
+ }
1506
+ if (requestPath === void 0) return false;
1507
+ const [pathOnly] = requestPath.split("?");
1508
+ if (pathOnly === void 0 || !pathOnly.startsWith(SECRET_PATH_PREFIX)) return false;
1509
+ return tokenMatches(expected, pathOnly.slice(SECRET_PATH_PREFIX.length));
1491
1510
  }
1492
1511
  async function startHttpTransport(createServerInstance, options) {
1493
1512
  const token = assertUsableToken(options.token);
@@ -1502,7 +1521,7 @@ async function startHttpTransport(createServerInstance, options) {
1502
1521
  await transport.handleRequest(request, response, body);
1503
1522
  };
1504
1523
  const httpServer = createServer((request, response) => {
1505
- if (!isAuthorized(request.headers.authorization, token)) {
1524
+ if (!isAuthorized(request.headers.authorization, token, request.url)) {
1506
1525
  refuse(
1507
1526
  response,
1508
1527
  401,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ogygie/mcp",
3
- "version": "0.10.0",
3
+ "version": "0.10.1",
4
4
  "description": "Ogygie MCP server: read-only access to the governance files and features of any Ogygie repo, the manifest as index. Ships built; runnable standalone or through `ogygie mcp`.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -28,7 +28,7 @@
28
28
  "tsx": "^4.20.0",
29
29
  "typescript": "^5.8.0",
30
30
  "vitest": "^3.2.0",
31
- "@ogygie/core": "0.10.0"
31
+ "@ogygie/core": "0.10.1"
32
32
  },
33
33
  "scripts": {
34
34
  "typecheck": "tsc -p tsconfig.json",