freshcontext-mcp 0.3.18 → 0.3.20

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.
@@ -1,8 +1,30 @@
1
- # FreshContext Signal Contract v1
2
-
3
- FreshContext Signal Contract v1 defines the Core shape for a retrieved signal before it is ranked, wrapped, stored, or passed to an agent workflow.
4
-
5
- It is an additive Core API. It does not change MCP tool schemas, Worker runtime behavior, D1 schema, Store scoring, feeds, or deployment behavior.
1
+ # FreshContext Signal Contract v1
2
+
3
+ FreshContext Signal Contract v1 is the current FreshContext input standard: the stable shape for candidate context that should be judged before it reaches a model.
4
+
5
+ In plain terms:
6
+
7
+ ```text
8
+ candidate context -> Signal Contract v1 -> FreshContext judgment -> decision-ready context
9
+ ```
10
+
11
+ The Signal Contract is live product architecture. It is used by Core normalization, `evaluate_context`, bring-your-own-context demos, reference adapter signal paths, and future batch validation.
12
+
13
+ Do not rename this with future-signal terminology. Future context signals, control signals, provenance confidence signals, and richer decision metadata are optional future layers on top of this stable input shape. They are not replacements for Signal Contract v1 and are not required fields today.
14
+
15
+ It is an additive Core API. It does not change MCP tool schemas, Worker runtime behavior, D1 schema, Store scoring, feeds, or deployment behavior.
16
+
17
+ ## Batch Validation Harness
18
+
19
+ Source checkouts include a small validation harness for testing larger Signal Contract v1 batches:
20
+
21
+ ```bash
22
+ npm run batch:validate -- examples/batches/signal-contract-v1.academic.json
23
+ ```
24
+
25
+ The harness reads caller-provided JSON, evaluates it through Core, summarizes status/date/decision counts, and prints a structured evidence block. It does not add required fields to the Signal Contract and does not fetch, crawl, scan folders, or call reference adapters.
26
+
27
+ Replay output includes concise decision explanations and small reason-code lists for top results and human-review mismatches. These are reporting aids for auditability: they surface whether relevance, freshness, date confidence, status, utility, score normalization, or Source Profile behavior influenced a treatment label. They do not change Core scoring, ranking, normalization, or decision thresholds, and they do not certify truth.
6
28
 
7
29
  ## Contract Version
8
30
 
@@ -16,9 +38,9 @@ Every normalized signal includes:
16
38
  contract_version: "freshcontext.signal.v1"
17
39
  ```
18
40
 
19
- ## Input Shape
20
-
21
- `FreshContextSignalInput` accepts the common fields used by adapters, agents, ranking, and future Store wiring:
41
+ ## Input Shape
42
+
43
+ `FreshContextSignalInput` accepts the common fields used by adapters, agents, ranking, `evaluate_context`, and future Store wiring:
22
44
 
23
45
  ```ts
24
46
  interface FreshContextSignalInput {
@@ -38,7 +60,21 @@ interface FreshContextSignalInput {
38
60
  }
39
61
  ```
40
62
 
41
- `published_at` is the canonical signal timestamp. `content_date` is accepted as an adapter/envelope compatibility alias.
63
+ `published_at` is the canonical signal timestamp. `content_date` is accepted as an adapter/envelope compatibility alias.
64
+
65
+ Minimal caller-provided input usually looks like:
66
+
67
+ ```json
68
+ {
69
+ "title": "Example source",
70
+ "content": "Candidate context text...",
71
+ "source": "https://example.com/source",
72
+ "source_type": "official_docs",
73
+ "published_at": "2026-06-01T00:00:00.000Z",
74
+ "retrieved_at": "2026-06-09T00:00:00.000Z",
75
+ "semantic_score": 0.92
76
+ }
77
+ ```
42
78
 
43
79
  ## Normalized Output
44
80
 
@@ -62,16 +98,166 @@ interface FreshContextSignal {
62
98
  }
63
99
  ```
64
100
 
65
- ## Normalization Rules
66
-
67
- - Missing or invalid `published_at` / `content_date` becomes `published_at: null`.
101
+ ## Normalization Rules
102
+
103
+ - Missing or invalid `published_at` / `content_date` becomes `published_at: null`.
68
104
  - `content_date` maps to `published_at` when `published_at` is absent.
69
105
  - Meaningfully future-dated timestamps are cleared and receive `date_confidence: "unknown"`.
70
106
  - Small clock skew is tolerated by the same Core freshness policy used by envelope scoring.
71
107
  - Failed, empty, timeout, blocked, or error-looking content becomes `status: "failed"`.
72
108
  - Missing, invalid, negative, or oversized `semantic_score` is clamped into `0..1`.
73
- - `metadata` is shallow-copied so normalization does not mutate caller-owned objects.
74
- - `reasons` records meaningful normalization changes.
109
+ - `metadata` is shallow-copied so normalization does not mutate caller-owned objects.
110
+ - `reasons` records meaningful normalization changes.
111
+
112
+ ## Examples
113
+
114
+ These examples are intentionally small. They show the current contract shape, not future optional metadata.
115
+
116
+ ### Valid Candidate Signals
117
+
118
+ Academic research:
119
+
120
+ ```json
121
+ {
122
+ "title": "A fresh retrieval-augmented generation benchmark",
123
+ "content": "The paper reports a 2026 benchmark for retrieval-augmented generation systems.",
124
+ "source": "https://arxiv.org/abs/2606.00001",
125
+ "source_type": "arxiv",
126
+ "published_at": "2026-06-01T09:00:00.000Z",
127
+ "retrieved_at": "2026-06-09T12:00:00.000Z",
128
+ "semantic_score": 0.94,
129
+ "metadata": {
130
+ "profile": "academic_research"
131
+ }
132
+ }
133
+ ```
134
+
135
+ Official docs:
136
+
137
+ ```json
138
+ {
139
+ "title": "API changelog",
140
+ "content": "The official changelog documents the current API behavior.",
141
+ "source": "https://docs.example.com/changelog",
142
+ "source_type": "official_docs",
143
+ "published_at": "2026-06-08T10:00:00.000Z",
144
+ "retrieved_at": "2026-06-09T12:00:00.000Z",
145
+ "semantic_score": 0.88
146
+ }
147
+ ```
148
+
149
+ Jobs/opportunities:
150
+
151
+ ```json
152
+ {
153
+ "title": "AI tools engineer",
154
+ "content": "A current remote role for an AI tools engineer.",
155
+ "source": "https://jobs.example.com/ai-tools-engineer",
156
+ "source_type": "jobs",
157
+ "published_at": "2026-06-07T08:00:00.000Z",
158
+ "retrieved_at": "2026-06-09T12:00:00.000Z",
159
+ "semantic_score": 0.86
160
+ }
161
+ ```
162
+
163
+ Market/finance:
164
+
165
+ ```json
166
+ {
167
+ "title": "Company quarterly update",
168
+ "content": "The company reported current quarter revenue and guidance.",
169
+ "source": "https://investors.example.com/q2-update",
170
+ "source_type": "finance",
171
+ "published_at": "2026-06-09T07:00:00.000Z",
172
+ "retrieved_at": "2026-06-09T12:00:00.000Z",
173
+ "semantic_score": 0.83
174
+ }
175
+ ```
176
+
177
+ Social pulse:
178
+
179
+ ```json
180
+ {
181
+ "title": "Developer discussion",
182
+ "content": "Developers are discussing setup friction and recent adoption.",
183
+ "source": "https://news.ycombinator.com/item?id=123456",
184
+ "source_type": "hackernews",
185
+ "published_at": "2026-06-09T11:00:00.000Z",
186
+ "retrieved_at": "2026-06-09T12:00:00.000Z",
187
+ "semantic_score": 0.71
188
+ }
189
+ ```
190
+
191
+ ### Invalid Or Risky Candidate Signals
192
+
193
+ Missing date:
194
+
195
+ ```json
196
+ {
197
+ "title": "Relevant source with no date",
198
+ "content": "Useful candidate context, but no publication timestamp is available.",
199
+ "source": "https://example.com/no-date",
200
+ "source_type": "official_docs",
201
+ "retrieved_at": "2026-06-09T12:00:00.000Z",
202
+ "semantic_score": 0.78
203
+ }
204
+ ```
205
+
206
+ Invalid timestamp:
207
+
208
+ ```json
209
+ {
210
+ "title": "Invalid date source",
211
+ "content": "Candidate context with malformed date metadata.",
212
+ "source": "https://example.com/bad-date",
213
+ "source_type": "official_docs",
214
+ "published_at": "not-a-date",
215
+ "retrieved_at": "2026-06-09T12:00:00.000Z",
216
+ "semantic_score": 0.78
217
+ }
218
+ ```
219
+
220
+ Meaningfully future-dated timestamp:
221
+
222
+ ```json
223
+ {
224
+ "title": "Future-dated source",
225
+ "content": "Candidate context whose publication timestamp is after retrieval time.",
226
+ "source": "https://example.com/future-date",
227
+ "source_type": "official_docs",
228
+ "published_at": "2026-06-09T12:06:00.000Z",
229
+ "retrieved_at": "2026-06-09T12:00:00.000Z",
230
+ "semantic_score": 0.78
231
+ }
232
+ ```
233
+
234
+ Failed/error-looking content:
235
+
236
+ ```json
237
+ {
238
+ "title": "Blocked source",
239
+ "content": "[Error] upstream timeout",
240
+ "source": "https://example.com/blocked",
241
+ "source_type": "official_docs",
242
+ "published_at": "2026-06-09T10:00:00.000Z",
243
+ "retrieved_at": "2026-06-09T12:00:00.000Z",
244
+ "semantic_score": 0.91
245
+ }
246
+ ```
247
+
248
+ Out-of-range semantic score:
249
+
250
+ ```json
251
+ {
252
+ "title": "Overscored source",
253
+ "content": "Candidate context with an out-of-range relevance score.",
254
+ "source": "https://example.com/overscored",
255
+ "source_type": "official_docs",
256
+ "published_at": "2026-06-09T10:00:00.000Z",
257
+ "retrieved_at": "2026-06-09T12:00:00.000Z",
258
+ "semantic_score": 1.7
259
+ }
260
+ ```
75
261
 
76
262
  ## Relationship to Existing Core Types
77
263
 
@@ -84,6 +270,16 @@ The signal contract does not replace existing Core types:
84
270
 
85
271
  The contract gives these surfaces a shared signal vocabulary without requiring Store, Worker, or MCP schema changes.
86
272
 
87
- ## Boundary
88
-
89
- Signal Contract v1 does not determine truth, certify data, or provide legal, medical, tax, or financial advice. It provides normalized context metadata for freshness, provenance, relevance, and workflow review.
273
+ ## Boundary
274
+
275
+ Signal Contract v1 does not determine truth, certify data, or provide legal, medical, tax, or financial advice. It provides normalized context metadata for freshness, provenance, relevance, and workflow review.
276
+
277
+ ## Future Metadata Boundary
278
+
279
+ Future context signals, control signals, ingestion quality signals, structure preservation signals, and provenance confidence signals may later improve decisions such as `cite_as_primary`, `needs_refresh`, `needs_verification`, or `exclude`.
280
+
281
+ Those are roadmap metadata layers. They should remain optional until tests prove they improve decisions. The public input contract should stay boring and stable:
282
+
283
+ ```text
284
+ title + content + source + source_type + published_at + retrieved_at + semantic_score
285
+ ```
@@ -31,7 +31,7 @@ MCP, REST, SDK, CLI, and future operator workflows are hosts over Core. They sho
31
31
 
32
32
  Adapters provide candidate context. They fetch, search, scrape, read, or receive source data, then turn that data into FreshContext-compatible signals.
33
33
 
34
- The 21 MCP tools in this repository are reference adapters, source-profile examples, and proof surfaces. They are useful, but they are not the product identity.
34
+ The named MCP tools in this repository are reference adapters, source-profile examples, and proof surfaces. They are useful, but they are not the product identity.
35
35
 
36
36
  They demonstrate that FreshContext can evaluate different information classes:
37
37
 
@@ -88,7 +88,7 @@ It does not add `retrieve(...)`, Operator mode, adapter selection, local file se
88
88
 
89
89
  ## Adapter Registry Metadata
90
90
 
91
- As of Pass 8-S, the 21 MCP tools are also represented as adapter metadata. The registry maps each current tool name to a future adapter identity, Source Profile, output mode, runtime kind, and migration risk.
91
+ As of Pass 8-S, the 21 named adapter tools are also represented as adapter metadata. The registry maps each adapter tool name to a future adapter identity, Source Profile, output mode, runtime kind, and migration risk. The generic `evaluate_context` MCP tool is not an adapter; it is a host interface over caller-provided candidate context.
92
92
 
93
93
  This registry is metadata-only. It does not change MCP behavior, adapter implementation behavior, Worker behavior, REST behavior, Core evaluation behavior, or runtime transport. It exists to make future extraction deliberate instead of ad hoc.
94
94
 
@@ -423,5 +423,5 @@ Sharper agent-facing sentence:
423
423
  FreshContext decides what context deserves to reach the model.
424
424
  ```
425
425
 
426
- Use the 21 tools as proof of breadth, not as the headline.
426
+ Use named reference adapters as proof of breadth, not as the headline.
427
427
 
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env node
2
- import { existsSync } from "node:fs";
3
- import { spawnSync } from "node:child_process";
2
+ import { existsSync } from "node:fs";
3
+ import { spawnSync } from "node:child_process";
4
+ import { join } from "node:path";
4
5
 
5
6
  const SOURCE_CHECKOUT_MESSAGE = [
6
7
  "This npm script is for the FreshContext source checkout.",
@@ -39,13 +40,19 @@ const commands = {
39
40
  command: "tsx",
40
41
  args: ["examples/evaluate-with-source-profile.ts"],
41
42
  },
42
- "demo:evaluate:file": {
43
- required: ["examples/evaluate-file.ts", "examples/sources.academic.example.json"],
44
- command: "tsx",
45
- args: ["examples/evaluate-file.ts", "examples/sources.academic.example.json"],
46
- passThroughArgs: true,
47
- },
48
- "smoke:stdio": {
43
+ "demo:evaluate:file": {
44
+ required: ["examples/evaluate-file.ts", "examples/sources.academic.example.json"],
45
+ command: "tsx",
46
+ args: ["examples/evaluate-file.ts", "examples/sources.academic.example.json"],
47
+ passThroughArgs: true,
48
+ },
49
+ "batch:validate": {
50
+ required: ["examples/validate-signal-batch.ts"],
51
+ command: "tsx",
52
+ args: ["examples/validate-signal-batch.ts"],
53
+ passThroughArgs: true,
54
+ },
55
+ "smoke:stdio": {
49
56
  required: ["scripts/smoke-stdio.mjs"],
50
57
  command: "node",
51
58
  args: ["scripts/smoke-stdio.mjs"],
@@ -91,16 +98,23 @@ const commands = {
91
98
  "tests/freshnessStamp.test.ts",
92
99
  "tests/hackernews.test.ts",
93
100
  "tests/arxivSignals.test.ts",
94
- "tests/arxivDecisionIntegration.test.ts",
95
- "tests/core.test.ts",
96
- "tests/rank.test.ts",
97
- "tests/workerEnvelope.test.ts",
98
- "tests/workerCoreEnvelopeParity.test.ts",
101
+ "tests/arxivDecisionIntegration.test.ts",
102
+ "tests/core.test.ts",
103
+ "tests/haPriV2GoldenVectors.test.ts",
104
+ "tests/signalContractExamples.test.ts",
105
+ "tests/batchValidationHarness.test.ts",
106
+ "tests/rank.test.ts",
107
+ "tests/workerEnvelope.test.ts",
108
+ "tests/packageScriptGuard.test.mjs",
109
+ "tests/adapterNetworkBoundary.test.ts",
110
+ "tests/workerRouteSecurity.test.ts",
111
+ "tests/workerCoreEnvelopeParity.test.ts",
99
112
  "tests/coreEnvelopeOptions.test.ts",
100
113
  "tests/mathSpine.test.ts",
101
114
  "tests/coreApiContract.test.ts",
102
115
  "tests/corePipeline.test.ts",
103
116
  "tests/decision.test.ts",
117
+ "tests/evaluateContextTool.test.ts",
104
118
  "tests/restHandler.test.ts",
105
119
  "tests/sourceProfiles.test.ts",
106
120
  "tests/adapterRegistry.test.ts",
@@ -117,20 +131,54 @@ if (!config) {
117
131
  process.exit(1);
118
132
  }
119
133
 
120
- const hasSourceCheckoutFiles = config.required.every((path) => existsSync(path));
121
- if (!hasSourceCheckoutFiles) {
122
- console.log(SOURCE_CHECKOUT_MESSAGE);
123
- process.exit(0);
124
- }
125
-
126
- const args = [
127
- ...config.args,
128
- ...(config.passThroughArgs ? process.argv.slice(3) : []),
129
- ];
130
- const child = spawnSync(config.command, args, {
131
- stdio: "inherit",
132
- shell: process.platform === "win32",
133
- });
134
+ const hasSourceCheckoutFiles = config.required.every((path) => existsSync(path));
135
+ if (!hasSourceCheckoutFiles) {
136
+ console.log(SOURCE_CHECKOUT_MESSAGE);
137
+ process.exit(0);
138
+ }
139
+
140
+ function resolveCommand(command, args) {
141
+ if (command === "node") return { command: process.execPath, args };
142
+
143
+ const localNodeEntrypoints = {
144
+ tsx: join("node_modules", "tsx", "dist", "cli.mjs"),
145
+ tsc: join("node_modules", "typescript", "bin", "tsc"),
146
+ };
147
+ const nodeEntrypoint = localNodeEntrypoints[command];
148
+ if (nodeEntrypoint && existsSync(nodeEntrypoint)) {
149
+ return { command: process.execPath, args: [nodeEntrypoint, ...args] };
150
+ }
151
+
152
+ const localBin = process.platform === "win32"
153
+ ? join("node_modules", ".bin", `${command}.cmd`)
154
+ : join("node_modules", ".bin", command);
155
+
156
+ if (existsSync(localBin)) return { command: localBin, args };
157
+ if (process.platform === "win32" && !command.endsWith(".cmd")) {
158
+ return { command: `${command}.cmd`, args };
159
+ }
160
+ return { command, args };
161
+ }
162
+
163
+ function validatePassThroughArgs(args) {
164
+ for (const arg of args) {
165
+ if (arg.includes("\0")) {
166
+ console.error("FreshContext package script arguments cannot contain null bytes.");
167
+ process.exit(1);
168
+ }
169
+ }
170
+ return args;
171
+ }
172
+
173
+ const args = [
174
+ ...config.args,
175
+ ...(config.passThroughArgs ? validatePassThroughArgs(process.argv.slice(3)) : []),
176
+ ];
177
+ const invocation = resolveCommand(config.command, args);
178
+ const child = spawnSync(invocation.command, invocation.args, {
179
+ stdio: "inherit",
180
+ shell: false,
181
+ });
134
182
 
135
183
  if (child.error) {
136
184
  console.error(child.error.message);
package/package.json CHANGED
@@ -1,18 +1,19 @@
1
1
  {
2
2
  "name": "freshcontext-mcp",
3
3
  "mcpName": "io.github.PrinceGabriel-lgtm/freshcontext",
4
- "version": "0.3.18",
5
- "description": "Real-time web intelligence for AI agents. 21 tools, no required API keys. Every result timestamped with a freshness score.",
4
+ "version": "0.3.20",
5
+ "description": "Context integrity infrastructure for AI agents and retrieval systems. Score, explain, and wrap candidate context before it reaches the model.",
6
6
  "keywords": [
7
7
  "mcp",
8
8
  "mcp-server",
9
9
  "ai-agents",
10
10
  "llm",
11
11
  "freshness",
12
- "web-scraping",
13
- "github-analytics",
14
- "hackernews",
15
- "yc",
12
+ "context-integrity",
13
+ "retrieval",
14
+ "provenance",
15
+ "source-profiles",
16
+ "rag",
16
17
  "typescript",
17
18
  "context",
18
19
  "model-context-protocol"
@@ -35,12 +36,17 @@
35
36
  ".env.example",
36
37
  "dist/",
37
38
  "!dist/apify.js",
39
+ "FRESHCONTEXT_SPEC.md",
40
+ "METHODOLOGY.md",
38
41
  "docs/API_DESIGN.md",
42
+ "docs/CLIENT_SETUP.md",
39
43
  "docs/CODEX_MCP_USAGE.md",
44
+ "docs/CORE_MCP_BOUNDARY.md",
40
45
  "docs/CORE_API.md",
41
46
  "docs/DEPENDENCY_DILIGENCE.md",
47
+ "docs/FUTURE_LANES.md",
42
48
  "docs/HA_PRI_V2_DESIGN.md",
43
- "docs/OPERATIONAL_DEMO_RUNBOOK.md",
49
+ "docs/HA_PRI_V2_PRODUCTION_ENFORCEMENT_PLAN.md",
44
50
  "docs/RELEASE_INTEGRITY.md",
45
51
  "docs/RELEASE_NOTES.md",
46
52
  "docs/SIGNAL_CONTRACT.md",
@@ -61,6 +67,7 @@
61
67
  "demo:arxiv": "node package-script-guard.mjs demo:arxiv",
62
68
  "demo:evaluate": "node package-script-guard.mjs demo:evaluate",
63
69
  "demo:evaluate:file": "node package-script-guard.mjs demo:evaluate:file",
70
+ "batch:validate": "node package-script-guard.mjs batch:validate",
64
71
  "smoke:stdio": "node package-script-guard.mjs smoke:stdio",
65
72
  "trust:gate": "node package-script-guard.mjs trust:gate",
66
73
  "trust:report": "node package-script-guard.mjs trust:report",
package/server.json CHANGED
@@ -1,18 +1,18 @@
1
1
  {
2
2
  "$schema": "https://static.modelcontextprotocol.io/schemas/2025-07-09/server.schema.json",
3
3
  "name": "io.github.PrinceGabriel-lgtm/freshcontext",
4
- "description": "Freshness-aware AI retrieval with 21 MCP tools for timestamped, decay-ranked live signals.",
4
+ "description": "Context integrity infrastructure for AI agents and retrieval systems. Evaluates caller-provided and adapter-sourced context before it reaches the model.",
5
5
  "repository": {
6
6
  "url": "https://github.com/PrinceGabriel-lgtm/freshcontext-mcp",
7
7
  "source": "github"
8
8
  },
9
- "version": "0.3.18",
9
+ "version": "0.3.20",
10
10
  "website_url": "https://freshcontext-site.pages.dev",
11
11
  "packages": [
12
12
  {
13
13
  "registryType": "npm",
14
14
  "identifier": "freshcontext-mcp",
15
- "version": "0.3.18",
15
+ "version": "0.3.20",
16
16
  "transport": {
17
17
  "type": "stdio"
18
18
  }