@akira-tl/forgerelay 1.2.1 → 1.2.2
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/CHANGELOG.md +9 -0
- package/dist/mcp/oauth/router.js +1 -1
- package/dist/mcp/panel/app.js +3 -2
- package/dist/mcp/server/transport/http-server.js +7 -2
- package/dist/workspaces/resources/skills.js +1 -2
- package/docs/chatgpt-coding-workflow.md +8 -8
- package/docs/configuration.md +7 -8
- package/docs/gotchas.md +4 -5
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,15 @@ All notable ForgeRelay changes are documented here.
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [1.2.2] - 2026-09-13
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- 修复带路径前缀的 `publicBaseUrl` 在 MCP SDK v2 下被 Origin 校验错误拒绝的问题;ForgeRelay 现在只从 canonical public URL 派生允许的 Origin hostname,同时继续拒绝 foreign / malformed Origin。
|
|
12
|
+
- OAuth authorization callback 现在带回 metadata 中公布的 `iss`,使 routed public URL 的现代 OAuth 流程保持 issuer 一致。
|
|
13
|
+
- MCP App 的 CSP `resourceDomains` / `connectDomains` 现在使用 URL Origin,而不是包含部署路径的完整 `publicBaseUrl`,避免 path-prefix 部署下 Activity Panel 只停留在 `Waiting for Activity Panel state.`。
|
|
14
|
+
- Skill 默认发现范围收敛为 Project `.agents/skills`、Project `.forgerelay/skills` 与 active ForgeRelay config `skills`;不再自动扫描全局 `~/.agents/skills` 或 `FORGERELAY_AGENT_DIR/skills`,显式 `FORGERELAY_SKILL_PATHS` 仍作为用户附加来源。
|
|
15
|
+
|
|
7
16
|
## [1.2.1] - 2026-09-13
|
|
8
17
|
|
|
9
18
|
### Fixed
|
package/dist/mcp/oauth/router.js
CHANGED
|
@@ -56,7 +56,7 @@ export function createForgeRelayAuthRouter(options) {
|
|
|
56
56
|
res.status(200).json({ ...tokens, ...(instanceId ? { instance_id: instanceId } : {}) });
|
|
57
57
|
});
|
|
58
58
|
}
|
|
59
|
-
router.use(authorizationPaths, authorizationHandler({ provider }));
|
|
59
|
+
router.use(authorizationPaths, authorizationHandler({ provider, issuerUrl }));
|
|
60
60
|
router.use(tokenPaths, tokenHandler({ provider }));
|
|
61
61
|
if (provider.clientsStore.registerClient && registrationEndpoint) {
|
|
62
62
|
router.use(registrationPaths, clientRegistrationHandler({ clientsStore: provider.clientsStore }));
|
package/dist/mcp/panel/app.js
CHANGED
|
@@ -64,9 +64,10 @@ function currentIdentity(config, fallbackRevision) {
|
|
|
64
64
|
return identity;
|
|
65
65
|
}
|
|
66
66
|
function activityPanelCsp(config) {
|
|
67
|
+
const publicOrigins = Array.from(new Set(config.publicBaseUrls.map((baseUrl) => new URL(baseUrl).origin)));
|
|
67
68
|
return {
|
|
68
|
-
resourceDomains:
|
|
69
|
-
connectDomains:
|
|
69
|
+
resourceDomains: publicOrigins,
|
|
70
|
+
connectDomains: publicOrigins,
|
|
70
71
|
};
|
|
71
72
|
}
|
|
72
73
|
async function readActivityPanelAppResource(config, fallbackRevision, requestedUri, transportSessionId) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
|
-
import { checkResourceAllowed, createMcpHandler, isInitializeRequest, isLegacyRequest, resourceUrlFromServerUrl, } from "@modelcontextprotocol/server";
|
|
2
|
+
import { checkResourceAllowed, createMcpHandler, isInitializeRequest, isLegacyRequest, localhostAllowedOrigins, resourceUrlFromServerUrl, } from "@modelcontextprotocol/server";
|
|
3
3
|
import { createMcpExpressApp, getOAuthProtectedResourceMetadataUrl, requireBearerAuth, } from "@modelcontextprotocol/express";
|
|
4
4
|
import { NodeStreamableHTTPServerTransport, toNodeHandler, toWebRequest, } from "@modelcontextprotocol/node";
|
|
5
5
|
import express from "express";
|
|
@@ -32,17 +32,22 @@ const MCP_TRANSPORT_CLEANUP_INTERVAL_MS = 5 * 60 * 1_000;
|
|
|
32
32
|
export function createHttpServer(config, options, createMcpServer) {
|
|
33
33
|
const incomingArtifactAdapters = options.incomingArtifactAdapters
|
|
34
34
|
?? [createOpenAIIncomingArtifactAdapter()];
|
|
35
|
+
const routeBaseUrls = config.publicBaseUrls.map((baseUrl) => new URL(baseUrl));
|
|
35
36
|
const allowedHosts = config.allowedHosts.includes("*")
|
|
36
37
|
? undefined
|
|
37
38
|
: Array.from(new Set([config.host, ...config.allowedHosts]));
|
|
39
|
+
const allowedOrigins = Array.from(new Set([
|
|
40
|
+
...localhostAllowedOrigins(),
|
|
41
|
+
...routeBaseUrls.map((baseUrl) => baseUrl.hostname),
|
|
42
|
+
]));
|
|
38
43
|
const app = createMcpExpressApp({
|
|
39
44
|
host: config.host,
|
|
40
45
|
...(allowedHosts ? { allowedHosts } : {}),
|
|
46
|
+
allowedOrigins,
|
|
41
47
|
});
|
|
42
48
|
const transports = new McpTransportRegistry({
|
|
43
49
|
maxTransports: MAX_MCP_TRANSPORT_SESSIONS,
|
|
44
50
|
});
|
|
45
|
-
const routeBaseUrls = config.publicBaseUrls.map((baseUrl) => new URL(baseUrl));
|
|
46
51
|
const mcpUrl = publicEndpointUrl(config.publicBaseUrl, "mcp");
|
|
47
52
|
const mcpPaths = publicEndpointPaths(routeBaseUrls, "mcp");
|
|
48
53
|
const activityPanelAssetsPaths = publicEndpointPaths(routeBaseUrls, "mcp-app-assets");
|
|
@@ -8,9 +8,8 @@ const FRONTMATTER_DELIMITER = "---";
|
|
|
8
8
|
export function effectiveSkillPaths(config, cwd) {
|
|
9
9
|
const defaultPathCandidates = [
|
|
10
10
|
resolve(cwd, ".agents", "skills"),
|
|
11
|
-
|
|
11
|
+
resolve(cwd, ".forgerelay", "skills"),
|
|
12
12
|
config.configSkillsDir,
|
|
13
|
-
join(config.agentDir, "skills"),
|
|
14
13
|
];
|
|
15
14
|
const defaultPaths = defaultPathCandidates.filter((path) => path !== undefined && existsSync(path));
|
|
16
15
|
const seen = new Set();
|
|
@@ -189,7 +189,8 @@ instructions before the requested file content. Side-effecting file tools and sh
|
|
|
189
189
|
commands discover instructions before execution; if new local instructions are
|
|
190
190
|
found, ForgeRelay returns them and requires the Agent to retry, so the side effect
|
|
191
191
|
does not occur before the relevant instructions are known. `FORGERELAY_AGENT_DIR`
|
|
192
|
-
is
|
|
192
|
+
is neither an instruction source nor an automatic Skill-discovery source; it remains
|
|
193
|
+
an integration runtime directory for supported Agent tooling.
|
|
193
194
|
|
|
194
195
|
## MCP capability loading
|
|
195
196
|
|
|
@@ -232,17 +233,16 @@ force the Host to discard a cached tool schema.
|
|
|
232
233
|
|
|
233
234
|
## Agent Skills
|
|
234
235
|
|
|
235
|
-
ForgeRelay discovers
|
|
236
|
+
ForgeRelay discovers Skills in precedence order from:
|
|
236
237
|
|
|
237
238
|
- project `.agents/skills`
|
|
238
|
-
-
|
|
239
|
-
- the active ForgeRelay config directory's `skills` folder
|
|
240
|
-
-
|
|
241
|
-
- paths from `FORGERELAY_SKILL_PATHS`
|
|
239
|
+
- project `.forgerelay/skills`
|
|
240
|
+
- the active ForgeRelay config directory's `skills` folder (`~/.forgerelay/skills` by default)
|
|
241
|
+
- paths explicitly added through `FORGERELAY_SKILL_PATHS`
|
|
242
242
|
|
|
243
|
-
These paths are discovery sources, not one shared ownership domain. `.agents/skills` is the open Agent Skills ecosystem and may contain files or symlinks managed by other Agent tooling. ForgeRelay-owned Skills
|
|
243
|
+
These paths are discovery sources, not one shared ownership domain. Project `.agents/skills` is the open Agent Skills ecosystem and may contain files or symlinks managed by other Agent tooling. ForgeRelay-owned project/system Skills stay under `.forgerelay/skills` and the active ForgeRelay config directory. ForgeRelay does not automatically scan global Agent runtime Skill directories such as `~/.agents/skills` or `FORGERELAY_AGENT_DIR/skills`.
|
|
244
244
|
|
|
245
|
-
Same-named collisions use the first source
|
|
245
|
+
Same-named collisions use the first source: project Agent Skills override project ForgeRelay Skills, which override system ForgeRelay Skills and explicit additional paths.
|
|
246
246
|
|
|
247
247
|
When a task matches an advertised skill, read its `SKILL.md` before using other
|
|
248
248
|
files in the skill directory.
|
package/docs/configuration.md
CHANGED
|
@@ -910,20 +910,19 @@ select a global instruction file; its `skills` child is an additional Agent Skil
|
|
|
910
910
|
| --- | --- |
|
|
911
911
|
| `FORGERELAY_SKILLS` | Set to `0` to hide skills. Enabled by default. |
|
|
912
912
|
| `FORGERELAY_SUBAGENTS` | Set to `1` to expose configured subagent profiles. |
|
|
913
|
-
| `FORGERELAY_AGENT_DIR` | Defaults to `~/.codex`;
|
|
913
|
+
| `FORGERELAY_AGENT_DIR` | Defaults to `~/.codex`; used by supported Agent integrations, not as an automatic Skill source. |
|
|
914
914
|
| `FORGERELAY_SKILL_PATHS` | Optional comma-separated additional skill directories. |
|
|
915
915
|
|
|
916
|
-
|
|
916
|
+
Skills are discovered in precedence order from:
|
|
917
917
|
|
|
918
918
|
- project `.agents/skills`
|
|
919
|
-
-
|
|
920
|
-
- the active ForgeRelay config directory's `skills` folder
|
|
921
|
-
- `
|
|
922
|
-
- paths from `FORGERELAY_SKILL_PATHS`
|
|
919
|
+
- project `.forgerelay/skills`
|
|
920
|
+
- the active ForgeRelay config directory's `skills` folder (`~/.forgerelay/skills` by default)
|
|
921
|
+
- paths explicitly added through `FORGERELAY_SKILL_PATHS`
|
|
923
922
|
|
|
924
|
-
|
|
923
|
+
Project `.agents/skills` belongs to the open Agent Skills ecosystem and may contain files or symlinks installed by other Agent tooling. ForgeRelay-owned project/system Skills stay under `.forgerelay/skills` and the active ForgeRelay config directory. Global Agent runtime directories such as `~/.agents/skills` and `FORGERELAY_AGENT_DIR/skills` are not scanned automatically.
|
|
925
924
|
|
|
926
|
-
When the same Skill name appears in more than one source, the first source wins
|
|
925
|
+
When the same Skill name appears in more than one source, the first source wins: project Agent Skills override project ForgeRelay Skills, which override system ForgeRelay Skills and explicit additional paths.
|
|
927
926
|
|
|
928
927
|
When subagents are enabled, canonical v1.2 profiles are discovered from:
|
|
929
928
|
|
package/docs/gotchas.md
CHANGED
|
@@ -192,15 +192,14 @@ Skills are enabled by default. Check:
|
|
|
192
192
|
FORGERELAY_SKILLS=1 forgerelay serve
|
|
193
193
|
```
|
|
194
194
|
|
|
195
|
-
Standard paths include:
|
|
195
|
+
Standard automatic discovery paths include:
|
|
196
196
|
|
|
197
197
|
- project `.agents/skills`
|
|
198
|
-
-
|
|
198
|
+
- project `.forgerelay/skills`
|
|
199
199
|
- active ForgeRelay config `skills` directory (`~/.forgerelay/skills` by default)
|
|
200
|
-
- `
|
|
201
|
-
- additional `FORGERELAY_SKILL_PATHS`
|
|
200
|
+
- additional paths explicitly configured through `FORGERELAY_SKILL_PATHS`
|
|
202
201
|
|
|
203
|
-
|
|
202
|
+
ForgeRelay does **not** automatically scan global Agent runtime Skill directories such as `~/.agents/skills` or `FORGERELAY_AGENT_DIR/skills`. Project `.agents/skills` remains the open Agent Skills source, while ForgeRelay-owned project/system Skills live under `.forgerelay/skills` and the active ForgeRelay config `skills` directory.
|
|
204
203
|
|
|
205
204
|
## Subagent profiles do not appear
|
|
206
205
|
|