neural-context-protocol 0.1.0a1__tar.gz
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.
- neural_context_protocol-0.1.0a1/PKG-INFO +242 -0
- neural_context_protocol-0.1.0a1/README.md +192 -0
- neural_context_protocol-0.1.0a1/ncp/__init__.py +35 -0
- neural_context_protocol-0.1.0a1/ncp/adapters/__init__.py +2 -0
- neural_context_protocol-0.1.0a1/ncp/adapters/anthropic.py +64 -0
- neural_context_protocol-0.1.0a1/ncp/adapters/base.py +76 -0
- neural_context_protocol-0.1.0a1/ncp/adapters/cohere.py +48 -0
- neural_context_protocol-0.1.0a1/ncp/adapters/gemini.py +39 -0
- neural_context_protocol-0.1.0a1/ncp/adapters/local.py +27 -0
- neural_context_protocol-0.1.0a1/ncp/adapters/mistral.py +46 -0
- neural_context_protocol-0.1.0a1/ncp/adapters/ollama.py +53 -0
- neural_context_protocol-0.1.0a1/ncp/adapters/openai.py +84 -0
- neural_context_protocol-0.1.0a1/ncp/api.py +210 -0
- neural_context_protocol-0.1.0a1/ncp/assembler.py +347 -0
- neural_context_protocol-0.1.0a1/ncp/benchmarks.py +269 -0
- neural_context_protocol-0.1.0a1/ncp/chunker.py +223 -0
- neural_context_protocol-0.1.0a1/ncp/cli.py +233 -0
- neural_context_protocol-0.1.0a1/ncp/coherence.py +101 -0
- neural_context_protocol-0.1.0a1/ncp/config.py +143 -0
- neural_context_protocol-0.1.0a1/ncp/costs.py +51 -0
- neural_context_protocol-0.1.0a1/ncp/dogfood.py +1351 -0
- neural_context_protocol-0.1.0a1/ncp/encoder.py +121 -0
- neural_context_protocol-0.1.0a1/ncp/hooks/__init__.py +2 -0
- neural_context_protocol-0.1.0a1/ncp/mcp/__init__.py +0 -0
- neural_context_protocol-0.1.0a1/ncp/mcp/server.py +537 -0
- neural_context_protocol-0.1.0a1/ncp/middleware/__init__.py +13 -0
- neural_context_protocol-0.1.0a1/ncp/middleware/base.py +88 -0
- neural_context_protocol-0.1.0a1/ncp/middleware/cost_tracking.py +45 -0
- neural_context_protocol-0.1.0a1/ncp/middleware/logging.py +67 -0
- neural_context_protocol-0.1.0a1/ncp/stores/__init__.py +2 -0
- neural_context_protocol-0.1.0a1/ncp/stores/base.py +96 -0
- neural_context_protocol-0.1.0a1/ncp/stores/sqlite.py +652 -0
- neural_context_protocol-0.1.0a1/ncp/templates/config.toml.example +28 -0
- neural_context_protocol-0.1.0a1/ncp/types.py +423 -0
- neural_context_protocol-0.1.0a1/ncp/version.py +1 -0
- neural_context_protocol-0.1.0a1/neural_context_protocol.egg-info/PKG-INFO +242 -0
- neural_context_protocol-0.1.0a1/neural_context_protocol.egg-info/SOURCES.txt +92 -0
- neural_context_protocol-0.1.0a1/neural_context_protocol.egg-info/dependency_links.txt +1 -0
- neural_context_protocol-0.1.0a1/neural_context_protocol.egg-info/entry_points.txt +2 -0
- neural_context_protocol-0.1.0a1/neural_context_protocol.egg-info/requires.txt +34 -0
- neural_context_protocol-0.1.0a1/neural_context_protocol.egg-info/top_level.txt +1 -0
- neural_context_protocol-0.1.0a1/pyproject.toml +79 -0
- neural_context_protocol-0.1.0a1/setup.cfg +4 -0
- neural_context_protocol-0.1.0a1/tests/test_adapters.py +377 -0
- neural_context_protocol-0.1.0a1/tests/test_api.py +146 -0
- neural_context_protocol-0.1.0a1/tests/test_assembler.py +148 -0
- neural_context_protocol-0.1.0a1/tests/test_assembler_phase3.py +335 -0
- neural_context_protocol-0.1.0a1/tests/test_benchmarks.py +59 -0
- neural_context_protocol-0.1.0a1/tests/test_chunker.py +100 -0
- neural_context_protocol-0.1.0a1/tests/test_cli.py +347 -0
- neural_context_protocol-0.1.0a1/tests/test_coherence.py +81 -0
- neural_context_protocol-0.1.0a1/tests/test_config.py +49 -0
- neural_context_protocol-0.1.0a1/tests/test_costs.py +33 -0
- neural_context_protocol-0.1.0a1/tests/test_dogfood.py +361 -0
- neural_context_protocol-0.1.0a1/tests/test_encoder.py +107 -0
- neural_context_protocol-0.1.0a1/tests/test_examples.py +58 -0
- neural_context_protocol-0.1.0a1/tests/test_imports.py +5 -0
- neural_context_protocol-0.1.0a1/tests/test_mcp_server.py +497 -0
- neural_context_protocol-0.1.0a1/tests/test_middleware.py +87 -0
- neural_context_protocol-0.1.0a1/tests/test_sqlite_store.py +231 -0
- neural_context_protocol-0.1.0a1/tests/test_types.py +256 -0
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: neural-context-protocol
|
|
3
|
+
Version: 0.1.0a1
|
|
4
|
+
Summary: Neural Context Protocol (NCP): bounded, persistent context for multi-agent pipelines.
|
|
5
|
+
Author: kulkarni2u
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/kulkarni2u/neural-context-protocol
|
|
8
|
+
Project-URL: Repository, https://github.com/kulkarni2u/neural-context-protocol
|
|
9
|
+
Project-URL: Issues, https://github.com/kulkarni2u/neural-context-protocol/issues
|
|
10
|
+
Keywords: mcp,agents,multi-agent,context,memory,sqlite,llm,protocol
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
18
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
19
|
+
Requires-Python: >=3.10
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
Requires-Dist: pydantic>=2.7
|
|
22
|
+
Requires-Dist: rank-bm25>=0.2.2
|
|
23
|
+
Requires-Dist: click>=8.1
|
|
24
|
+
Requires-Dist: rich>=13.0
|
|
25
|
+
Requires-Dist: httpx>=0.27
|
|
26
|
+
Requires-Dist: anyio>=4.3
|
|
27
|
+
Requires-Dist: orjson>=3.10
|
|
28
|
+
Requires-Dist: structlog>=24.0
|
|
29
|
+
Provides-Extra: providers
|
|
30
|
+
Requires-Dist: anthropic; extra == "providers"
|
|
31
|
+
Requires-Dist: openai; extra == "providers"
|
|
32
|
+
Requires-Dist: google-generativeai; extra == "providers"
|
|
33
|
+
Requires-Dist: mistralai; extra == "providers"
|
|
34
|
+
Requires-Dist: cohere; extra == "providers"
|
|
35
|
+
Provides-Extra: http
|
|
36
|
+
Requires-Dist: aiohttp; extra == "http"
|
|
37
|
+
Provides-Extra: redis
|
|
38
|
+
Requires-Dist: redis; extra == "redis"
|
|
39
|
+
Provides-Extra: pgvector
|
|
40
|
+
Requires-Dist: psycopg2-binary; extra == "pgvector"
|
|
41
|
+
Requires-Dist: pgvector; extra == "pgvector"
|
|
42
|
+
Provides-Extra: dev
|
|
43
|
+
Requires-Dist: build; extra == "dev"
|
|
44
|
+
Requires-Dist: pytest; extra == "dev"
|
|
45
|
+
Requires-Dist: pytest-asyncio; extra == "dev"
|
|
46
|
+
Requires-Dist: pytest-httpx; extra == "dev"
|
|
47
|
+
Requires-Dist: pytest-cov; extra == "dev"
|
|
48
|
+
Requires-Dist: ruff; extra == "dev"
|
|
49
|
+
Requires-Dist: mypy; extra == "dev"
|
|
50
|
+
|
|
51
|
+
# Neural Context Protocol
|
|
52
|
+
|
|
53
|
+
[](https://github.com/kulkarni2u/neural-context-protocol/actions/workflows/ci.yml)
|
|
54
|
+

|
|
55
|
+

|
|
56
|
+
|
|
57
|
+
Neural Context Protocol (NCP) is a local-first context runtime for multi-agent
|
|
58
|
+
systems. It keeps context bounded, persists useful memory across turns and
|
|
59
|
+
restarts, and exposes that shared context over MCP so multiple tools can work
|
|
60
|
+
from the same state instead of replaying full history.
|
|
61
|
+
|
|
62
|
+
In the included benchmarks, NCP reduced peak prompt size by `17.52x` on a
|
|
63
|
+
coding pipeline and `16.35x` on a research pipeline versus naive history replay.
|
|
64
|
+
|
|
65
|
+
## Why NCP
|
|
66
|
+
|
|
67
|
+
Multi-agent workflows usually break down in three predictable ways:
|
|
68
|
+
|
|
69
|
+
- prompt history keeps growing until token cost and latency get ugly
|
|
70
|
+
- agents lose useful state between turns or after a restart
|
|
71
|
+
- each tool has its own silo, so context does not move cleanly across workers
|
|
72
|
+
|
|
73
|
+
NCP addresses that with:
|
|
74
|
+
|
|
75
|
+
- bounded context assembly for the current turn
|
|
76
|
+
- durable shared memory in a project-local SQLite store
|
|
77
|
+
- targeted mid-turn retrieval with `ncp_fetch`
|
|
78
|
+
- cross-agent signaling with whispers
|
|
79
|
+
- one MCP surface that multiple coding tools can share
|
|
80
|
+
|
|
81
|
+
## What Is Proven Today
|
|
82
|
+
|
|
83
|
+
This repo is in an early alpha V1 state with a SQLite-first runtime and
|
|
84
|
+
HTTP/SSE MCP as the public transport.
|
|
85
|
+
|
|
86
|
+
What is already proven in this repository:
|
|
87
|
+
|
|
88
|
+
- Claude and OpenCode both connect to the same NCP MCP server over HTTP
|
|
89
|
+
- both hosts can write shared memory through MCP
|
|
90
|
+
- both hosts can retrieve memory written by the other host
|
|
91
|
+
- both hosts can deliver and receive whispers through the shared MCP runtime
|
|
92
|
+
- restart persistence is validated by the dogfood harness
|
|
93
|
+
- bounded-context benchmarks are reproducible and show large prompt reduction
|
|
94
|
+
|
|
95
|
+
Current benchmark snapshot:
|
|
96
|
+
|
|
97
|
+
- coding pipeline: peak `174` NCP tokens vs `1927` naive replay, `17.52x` reduction
|
|
98
|
+
- research pipeline: peak `156` NCP tokens vs `1700` naive replay, `16.35x` reduction
|
|
99
|
+
|
|
100
|
+
## Quick Start
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
pip install -e .
|
|
104
|
+
ncp init
|
|
105
|
+
ncp serve --host 127.0.0.1 --port 4242 --cwd /path/to/project
|
|
106
|
+
ncp status --cwd /path/to/project
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Expected success signals:
|
|
110
|
+
|
|
111
|
+
- `ncp init` creates `.ncp/config.toml` and `CLAUDE.md`
|
|
112
|
+
- `ncp serve` starts the local HTTP MCP server on `127.0.0.1:4242`
|
|
113
|
+
- `ncp status` prints store metrics such as chunk count and whisper count
|
|
114
|
+
|
|
115
|
+
Published alpha install path:
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
pip install neural-context-protocol
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
For a deeper setup path, see [docs/NCP_SETUP.md](./docs/NCP_SETUP.md).
|
|
122
|
+
|
|
123
|
+
## How It Works
|
|
124
|
+
|
|
125
|
+
NCP keeps one shared SQLite store per project and serves it over MCP:
|
|
126
|
+
|
|
127
|
+
```text
|
|
128
|
+
Claude Code ─┐
|
|
129
|
+
Codex ─┼→ ncp serve (HTTP/SSE MCP) → .ncp/store.db
|
|
130
|
+
OpenCode ─┘
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Each agent turn works roughly like this:
|
|
134
|
+
|
|
135
|
+
1. call `ncp_get_context`
|
|
136
|
+
2. get a bounded, assembled context block for the current role and task
|
|
137
|
+
3. optionally call `ncp_fetch` for targeted retrieval mid-turn
|
|
138
|
+
4. persist useful results with `ncp_write_memory`
|
|
139
|
+
5. send light-weight cross-agent signals with `ncp_emit_whisper`
|
|
140
|
+
|
|
141
|
+
Example assembled context:
|
|
142
|
+
|
|
143
|
+
```text
|
|
144
|
+
[NCP:CONSCIOUS]
|
|
145
|
+
agent:planner role:plan task:verify_shared_memory slot:bounded_context
|
|
146
|
+
|
|
147
|
+
[NCP:SUBCON]
|
|
148
|
+
chunk:sub_2267717ed22a layer:semantic
|
|
149
|
+
opencode_http_probe_20260524T230734Z
|
|
150
|
+
|
|
151
|
+
[NCP:WHISPERS]
|
|
152
|
+
wsp from:opencode to:claude t:nudge c:0.96 age:1s
|
|
153
|
+
whisper_probe_opencode_to_claude_20260524T232132Z
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
## MCP Transport
|
|
157
|
+
|
|
158
|
+
NCP’s public transport is HTTP/SSE MCP:
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
ncp serve --host 127.0.0.1 --port 4242 --cwd /path/to/project
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
Endpoints:
|
|
165
|
+
|
|
166
|
+
- `GET /healthz`
|
|
167
|
+
- `GET /sse`
|
|
168
|
+
- `POST /mcp`
|
|
169
|
+
|
|
170
|
+
Use this endpoint in MCP host configs:
|
|
171
|
+
|
|
172
|
+
- `http://127.0.0.1:4242/mcp`
|
|
173
|
+
|
|
174
|
+
The public HTTP path is validated end to end by the dogfood harness, not just
|
|
175
|
+
by unit tests.
|
|
176
|
+
|
|
177
|
+
## Benchmarks
|
|
178
|
+
|
|
179
|
+
Runnable benchmark commands:
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
python3 benchmarks/coding_pipeline/run.py --turns 40
|
|
183
|
+
python3 benchmarks/research_pipeline/run.py --turns 36
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
Benchmark write-ups:
|
|
187
|
+
|
|
188
|
+
- [docs/NCP_BENCHMARK_CODING_PIPELINE.md](./docs/NCP_BENCHMARK_CODING_PIPELINE.md)
|
|
189
|
+
- [docs/NCP_BENCHMARK_RESEARCH_PIPELINE.md](./docs/NCP_BENCHMARK_RESEARCH_PIPELINE.md)
|
|
190
|
+
|
|
191
|
+
## Examples
|
|
192
|
+
|
|
193
|
+
Runnable examples:
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
python3 examples/01_quickstart.py
|
|
197
|
+
python3 examples/02_multi_agent.py
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
Integration examples:
|
|
201
|
+
|
|
202
|
+
- `examples/06_claude_code/` - Claude Code setup and MCP config
|
|
203
|
+
- `examples/07_codex_cli/` - Codex CLI MCP config and session loop
|
|
204
|
+
|
|
205
|
+
## Current Scope
|
|
206
|
+
|
|
207
|
+
This repository currently ships:
|
|
208
|
+
|
|
209
|
+
- core NCP types and encoder
|
|
210
|
+
- chunking and bounded assembly
|
|
211
|
+
- SQLite-backed persistence
|
|
212
|
+
- HTTP/SSE MCP server
|
|
213
|
+
- dogfood validation harness
|
|
214
|
+
- local adapter plus provider adapter surface
|
|
215
|
+
- release preflight script
|
|
216
|
+
- minimal CI for `ruff`, `pytest`, and `build`
|
|
217
|
+
|
|
218
|
+
Next release step:
|
|
219
|
+
|
|
220
|
+
- publish the first alpha release
|
|
221
|
+
|
|
222
|
+
## Documentation
|
|
223
|
+
|
|
224
|
+
- [docs/NCP_SETUP.md](./docs/NCP_SETUP.md) - install and first-run setup
|
|
225
|
+
- [docs/NCP_PROTOCOL_SPEC.md](./docs/NCP_PROTOCOL_SPEC.md) - normative protocol reference
|
|
226
|
+
- [docs/NCP_MCP_DOGFOOD_LOOP.md](./docs/NCP_MCP_DOGFOOD_LOOP.md) - deterministic MCP proof path
|
|
227
|
+
- [docs/NCP_PROVIDER_PARITY_BASELINE.md](./docs/NCP_PROVIDER_PARITY_BASELINE.md) - current live host parity snapshot
|
|
228
|
+
- [CHANGELOG.md](./CHANGELOG.md) - release-facing change summary
|
|
229
|
+
|
|
230
|
+
## Release Preflight
|
|
231
|
+
|
|
232
|
+
```bash
|
|
233
|
+
bash scripts/release_preflight.sh
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
<details>
|
|
237
|
+
<summary>Provider notes</summary>
|
|
238
|
+
|
|
239
|
+
- `GeminiAdapter` currently uses `google.generativeai`, which is deprecated upstream. The adapter is functionally green in tests, but should migrate to `google.genai` in a future pass.
|
|
240
|
+
- `CohereAdapter` is functionally green, but the current upstream SDK emits Python deprecation warnings during tests.
|
|
241
|
+
|
|
242
|
+
</details>
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
# Neural Context Protocol
|
|
2
|
+
|
|
3
|
+
[](https://github.com/kulkarni2u/neural-context-protocol/actions/workflows/ci.yml)
|
|
4
|
+

|
|
5
|
+

|
|
6
|
+
|
|
7
|
+
Neural Context Protocol (NCP) is a local-first context runtime for multi-agent
|
|
8
|
+
systems. It keeps context bounded, persists useful memory across turns and
|
|
9
|
+
restarts, and exposes that shared context over MCP so multiple tools can work
|
|
10
|
+
from the same state instead of replaying full history.
|
|
11
|
+
|
|
12
|
+
In the included benchmarks, NCP reduced peak prompt size by `17.52x` on a
|
|
13
|
+
coding pipeline and `16.35x` on a research pipeline versus naive history replay.
|
|
14
|
+
|
|
15
|
+
## Why NCP
|
|
16
|
+
|
|
17
|
+
Multi-agent workflows usually break down in three predictable ways:
|
|
18
|
+
|
|
19
|
+
- prompt history keeps growing until token cost and latency get ugly
|
|
20
|
+
- agents lose useful state between turns or after a restart
|
|
21
|
+
- each tool has its own silo, so context does not move cleanly across workers
|
|
22
|
+
|
|
23
|
+
NCP addresses that with:
|
|
24
|
+
|
|
25
|
+
- bounded context assembly for the current turn
|
|
26
|
+
- durable shared memory in a project-local SQLite store
|
|
27
|
+
- targeted mid-turn retrieval with `ncp_fetch`
|
|
28
|
+
- cross-agent signaling with whispers
|
|
29
|
+
- one MCP surface that multiple coding tools can share
|
|
30
|
+
|
|
31
|
+
## What Is Proven Today
|
|
32
|
+
|
|
33
|
+
This repo is in an early alpha V1 state with a SQLite-first runtime and
|
|
34
|
+
HTTP/SSE MCP as the public transport.
|
|
35
|
+
|
|
36
|
+
What is already proven in this repository:
|
|
37
|
+
|
|
38
|
+
- Claude and OpenCode both connect to the same NCP MCP server over HTTP
|
|
39
|
+
- both hosts can write shared memory through MCP
|
|
40
|
+
- both hosts can retrieve memory written by the other host
|
|
41
|
+
- both hosts can deliver and receive whispers through the shared MCP runtime
|
|
42
|
+
- restart persistence is validated by the dogfood harness
|
|
43
|
+
- bounded-context benchmarks are reproducible and show large prompt reduction
|
|
44
|
+
|
|
45
|
+
Current benchmark snapshot:
|
|
46
|
+
|
|
47
|
+
- coding pipeline: peak `174` NCP tokens vs `1927` naive replay, `17.52x` reduction
|
|
48
|
+
- research pipeline: peak `156` NCP tokens vs `1700` naive replay, `16.35x` reduction
|
|
49
|
+
|
|
50
|
+
## Quick Start
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
pip install -e .
|
|
54
|
+
ncp init
|
|
55
|
+
ncp serve --host 127.0.0.1 --port 4242 --cwd /path/to/project
|
|
56
|
+
ncp status --cwd /path/to/project
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Expected success signals:
|
|
60
|
+
|
|
61
|
+
- `ncp init` creates `.ncp/config.toml` and `CLAUDE.md`
|
|
62
|
+
- `ncp serve` starts the local HTTP MCP server on `127.0.0.1:4242`
|
|
63
|
+
- `ncp status` prints store metrics such as chunk count and whisper count
|
|
64
|
+
|
|
65
|
+
Published alpha install path:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
pip install neural-context-protocol
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
For a deeper setup path, see [docs/NCP_SETUP.md](./docs/NCP_SETUP.md).
|
|
72
|
+
|
|
73
|
+
## How It Works
|
|
74
|
+
|
|
75
|
+
NCP keeps one shared SQLite store per project and serves it over MCP:
|
|
76
|
+
|
|
77
|
+
```text
|
|
78
|
+
Claude Code ─┐
|
|
79
|
+
Codex ─┼→ ncp serve (HTTP/SSE MCP) → .ncp/store.db
|
|
80
|
+
OpenCode ─┘
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Each agent turn works roughly like this:
|
|
84
|
+
|
|
85
|
+
1. call `ncp_get_context`
|
|
86
|
+
2. get a bounded, assembled context block for the current role and task
|
|
87
|
+
3. optionally call `ncp_fetch` for targeted retrieval mid-turn
|
|
88
|
+
4. persist useful results with `ncp_write_memory`
|
|
89
|
+
5. send light-weight cross-agent signals with `ncp_emit_whisper`
|
|
90
|
+
|
|
91
|
+
Example assembled context:
|
|
92
|
+
|
|
93
|
+
```text
|
|
94
|
+
[NCP:CONSCIOUS]
|
|
95
|
+
agent:planner role:plan task:verify_shared_memory slot:bounded_context
|
|
96
|
+
|
|
97
|
+
[NCP:SUBCON]
|
|
98
|
+
chunk:sub_2267717ed22a layer:semantic
|
|
99
|
+
opencode_http_probe_20260524T230734Z
|
|
100
|
+
|
|
101
|
+
[NCP:WHISPERS]
|
|
102
|
+
wsp from:opencode to:claude t:nudge c:0.96 age:1s
|
|
103
|
+
whisper_probe_opencode_to_claude_20260524T232132Z
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## MCP Transport
|
|
107
|
+
|
|
108
|
+
NCP’s public transport is HTTP/SSE MCP:
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
ncp serve --host 127.0.0.1 --port 4242 --cwd /path/to/project
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Endpoints:
|
|
115
|
+
|
|
116
|
+
- `GET /healthz`
|
|
117
|
+
- `GET /sse`
|
|
118
|
+
- `POST /mcp`
|
|
119
|
+
|
|
120
|
+
Use this endpoint in MCP host configs:
|
|
121
|
+
|
|
122
|
+
- `http://127.0.0.1:4242/mcp`
|
|
123
|
+
|
|
124
|
+
The public HTTP path is validated end to end by the dogfood harness, not just
|
|
125
|
+
by unit tests.
|
|
126
|
+
|
|
127
|
+
## Benchmarks
|
|
128
|
+
|
|
129
|
+
Runnable benchmark commands:
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
python3 benchmarks/coding_pipeline/run.py --turns 40
|
|
133
|
+
python3 benchmarks/research_pipeline/run.py --turns 36
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
Benchmark write-ups:
|
|
137
|
+
|
|
138
|
+
- [docs/NCP_BENCHMARK_CODING_PIPELINE.md](./docs/NCP_BENCHMARK_CODING_PIPELINE.md)
|
|
139
|
+
- [docs/NCP_BENCHMARK_RESEARCH_PIPELINE.md](./docs/NCP_BENCHMARK_RESEARCH_PIPELINE.md)
|
|
140
|
+
|
|
141
|
+
## Examples
|
|
142
|
+
|
|
143
|
+
Runnable examples:
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
python3 examples/01_quickstart.py
|
|
147
|
+
python3 examples/02_multi_agent.py
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
Integration examples:
|
|
151
|
+
|
|
152
|
+
- `examples/06_claude_code/` - Claude Code setup and MCP config
|
|
153
|
+
- `examples/07_codex_cli/` - Codex CLI MCP config and session loop
|
|
154
|
+
|
|
155
|
+
## Current Scope
|
|
156
|
+
|
|
157
|
+
This repository currently ships:
|
|
158
|
+
|
|
159
|
+
- core NCP types and encoder
|
|
160
|
+
- chunking and bounded assembly
|
|
161
|
+
- SQLite-backed persistence
|
|
162
|
+
- HTTP/SSE MCP server
|
|
163
|
+
- dogfood validation harness
|
|
164
|
+
- local adapter plus provider adapter surface
|
|
165
|
+
- release preflight script
|
|
166
|
+
- minimal CI for `ruff`, `pytest`, and `build`
|
|
167
|
+
|
|
168
|
+
Next release step:
|
|
169
|
+
|
|
170
|
+
- publish the first alpha release
|
|
171
|
+
|
|
172
|
+
## Documentation
|
|
173
|
+
|
|
174
|
+
- [docs/NCP_SETUP.md](./docs/NCP_SETUP.md) - install and first-run setup
|
|
175
|
+
- [docs/NCP_PROTOCOL_SPEC.md](./docs/NCP_PROTOCOL_SPEC.md) - normative protocol reference
|
|
176
|
+
- [docs/NCP_MCP_DOGFOOD_LOOP.md](./docs/NCP_MCP_DOGFOOD_LOOP.md) - deterministic MCP proof path
|
|
177
|
+
- [docs/NCP_PROVIDER_PARITY_BASELINE.md](./docs/NCP_PROVIDER_PARITY_BASELINE.md) - current live host parity snapshot
|
|
178
|
+
- [CHANGELOG.md](./CHANGELOG.md) - release-facing change summary
|
|
179
|
+
|
|
180
|
+
## Release Preflight
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
bash scripts/release_preflight.sh
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
<details>
|
|
187
|
+
<summary>Provider notes</summary>
|
|
188
|
+
|
|
189
|
+
- `GeminiAdapter` currently uses `google.generativeai`, which is deprecated upstream. The adapter is functionally green in tests, but should migrate to `google.genai` in a future pass.
|
|
190
|
+
- `CohereAdapter` is functionally green, but the current upstream SDK emits Python deprecation warnings during tests.
|
|
191
|
+
|
|
192
|
+
</details>
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"""Public package surface for Neural Context Protocol."""
|
|
2
|
+
|
|
3
|
+
from .api import agent, configure, emit, get_context, run, stream, write_memory
|
|
4
|
+
from .benchmarks import estimate_tokens, run_coding_pipeline_benchmark, run_research_pipeline_benchmark
|
|
5
|
+
from .dogfood import (
|
|
6
|
+
get_live_provider_readiness,
|
|
7
|
+
load_dogfood_adapter,
|
|
8
|
+
run_adapter_continuation_dogfood_loop,
|
|
9
|
+
run_canonical_dogfood_loop,
|
|
10
|
+
run_canonical_http_dogfood_loop,
|
|
11
|
+
run_live_adapter_continuation_attempt,
|
|
12
|
+
run_repeatability_dogfood_loop,
|
|
13
|
+
)
|
|
14
|
+
from .version import __version__
|
|
15
|
+
|
|
16
|
+
__all__ = [
|
|
17
|
+
"__version__",
|
|
18
|
+
"agent",
|
|
19
|
+
"configure",
|
|
20
|
+
"estimate_tokens",
|
|
21
|
+
"emit",
|
|
22
|
+
"get_live_provider_readiness",
|
|
23
|
+
"get_context",
|
|
24
|
+
"load_dogfood_adapter",
|
|
25
|
+
"run_adapter_continuation_dogfood_loop",
|
|
26
|
+
"run_canonical_dogfood_loop",
|
|
27
|
+
"run_canonical_http_dogfood_loop",
|
|
28
|
+
"run_live_adapter_continuation_attempt",
|
|
29
|
+
"run_repeatability_dogfood_loop",
|
|
30
|
+
"run",
|
|
31
|
+
"run_coding_pipeline_benchmark",
|
|
32
|
+
"run_research_pipeline_benchmark",
|
|
33
|
+
"stream",
|
|
34
|
+
"write_memory",
|
|
35
|
+
]
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from collections.abc import Iterator
|
|
4
|
+
from os import environ
|
|
5
|
+
|
|
6
|
+
from ncp.adapters.base import BaseAdapter
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class AnthropicAdapter(BaseAdapter):
|
|
10
|
+
@property
|
|
11
|
+
def ctx_window(self) -> int:
|
|
12
|
+
return 200000
|
|
13
|
+
|
|
14
|
+
def __init__(
|
|
15
|
+
self,
|
|
16
|
+
api_key: str = "",
|
|
17
|
+
model: str = "claude-sonnet-4-20250514",
|
|
18
|
+
max_tokens: int = 4096,
|
|
19
|
+
timeout: float = 120.0,
|
|
20
|
+
) -> None:
|
|
21
|
+
try:
|
|
22
|
+
import anthropic
|
|
23
|
+
except ImportError as err:
|
|
24
|
+
raise ImportError(
|
|
25
|
+
"anthropic is required. Install it with: pip install 'ncp-sdk[providers]'"
|
|
26
|
+
) from err
|
|
27
|
+
self._anthropic = anthropic
|
|
28
|
+
resolved_key = api_key or environ.get("ANTHROPIC_API_KEY", "")
|
|
29
|
+
self._client = anthropic.Anthropic(
|
|
30
|
+
api_key=self._require_api_key(resolved_key, env_var="ANTHROPIC_API_KEY"),
|
|
31
|
+
timeout=timeout,
|
|
32
|
+
)
|
|
33
|
+
self._model = model
|
|
34
|
+
self._max_tokens = max_tokens
|
|
35
|
+
|
|
36
|
+
def call(self, ncp_context: str, user_turn: str) -> str:
|
|
37
|
+
msg = self._run_provider_call(
|
|
38
|
+
lambda: self._client.messages.create(
|
|
39
|
+
model=self._model,
|
|
40
|
+
max_tokens=self._max_tokens,
|
|
41
|
+
system=ncp_context,
|
|
42
|
+
messages=[{"role": "user", "content": user_turn}],
|
|
43
|
+
),
|
|
44
|
+
provider="Anthropic",
|
|
45
|
+
timeout_types=(self._anthropic.APITimeoutError, TimeoutError),
|
|
46
|
+
)
|
|
47
|
+
texts = [b.text for b in msg.content if b.type == "text"]
|
|
48
|
+
return self._coerce_text("".join(texts), provider="Anthropic")
|
|
49
|
+
|
|
50
|
+
def stream(self, ncp_context: str, user_turn: str) -> Iterator[str]:
|
|
51
|
+
stream_ctx = self._run_provider_call(
|
|
52
|
+
lambda: self._client.messages.stream(
|
|
53
|
+
model=self._model,
|
|
54
|
+
max_tokens=self._max_tokens,
|
|
55
|
+
system=ncp_context,
|
|
56
|
+
messages=[{"role": "user", "content": user_turn}],
|
|
57
|
+
),
|
|
58
|
+
provider="Anthropic",
|
|
59
|
+
timeout_types=(self._anthropic.APITimeoutError, TimeoutError),
|
|
60
|
+
)
|
|
61
|
+
with stream_ctx as stream:
|
|
62
|
+
for event in stream:
|
|
63
|
+
if event.type == "content_block_delta" and event.delta.type == "text_delta":
|
|
64
|
+
yield event.delta.text
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"""Base adapter contract."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from abc import ABC, abstractmethod
|
|
6
|
+
from collections.abc import Iterator
|
|
7
|
+
from typing import Callable, TypeVar
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class NCPAdapterError(RuntimeError):
|
|
11
|
+
"""Base class for provider adapter failures."""
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class NCPAdapterConfigurationError(NCPAdapterError):
|
|
15
|
+
"""Raised when an adapter is misconfigured before making a call."""
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class NCPAdapterTimeoutError(NCPAdapterError):
|
|
19
|
+
"""Raised when a provider call times out."""
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class NCPAdapterResponseError(NCPAdapterError):
|
|
23
|
+
"""Raised when a provider returns an unusable response."""
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
_T = TypeVar("_T")
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class BaseAdapter(ABC):
|
|
30
|
+
"""Minimal provider adapter contract for the first NCP API slice."""
|
|
31
|
+
|
|
32
|
+
@property
|
|
33
|
+
def ctx_window(self) -> int:
|
|
34
|
+
return 200000
|
|
35
|
+
|
|
36
|
+
@abstractmethod
|
|
37
|
+
def call(self, ncp_context: str, user_turn: str) -> str:
|
|
38
|
+
"""Return a blocking response for one assembled context."""
|
|
39
|
+
|
|
40
|
+
def stream(self, ncp_context: str, user_turn: str) -> Iterator[str]:
|
|
41
|
+
"""Yield a streamed response for one assembled context.
|
|
42
|
+
|
|
43
|
+
Tier 2 providers override only if they support streaming.
|
|
44
|
+
"""
|
|
45
|
+
raise NotImplementedError(
|
|
46
|
+
f"{type(self).__name__} does not support streaming in NCP V1; use blocking call()"
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
def _require_api_key(self, api_key: str, *, env_var: str) -> str:
|
|
50
|
+
if api_key.strip():
|
|
51
|
+
return api_key
|
|
52
|
+
raise NCPAdapterConfigurationError(
|
|
53
|
+
f"{type(self).__name__} requires {env_var}; configure it or pass api_key explicitly"
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
def _coerce_text(self, value: str | None, *, provider: str) -> str:
|
|
57
|
+
text = (value or "").strip()
|
|
58
|
+
if text:
|
|
59
|
+
return text
|
|
60
|
+
raise NCPAdapterResponseError(f"{provider} returned an empty text response")
|
|
61
|
+
|
|
62
|
+
def _run_provider_call(
|
|
63
|
+
self,
|
|
64
|
+
call: Callable[[], _T],
|
|
65
|
+
*,
|
|
66
|
+
provider: str,
|
|
67
|
+
timeout_types: tuple[type[BaseException], ...] = (TimeoutError,),
|
|
68
|
+
) -> _T:
|
|
69
|
+
try:
|
|
70
|
+
return call()
|
|
71
|
+
except NCPAdapterError:
|
|
72
|
+
raise
|
|
73
|
+
except timeout_types as exc:
|
|
74
|
+
raise NCPAdapterTimeoutError(f"{provider} timed out: {exc}") from exc
|
|
75
|
+
except Exception as exc:
|
|
76
|
+
raise NCPAdapterError(f"{provider} call failed: {exc}") from exc
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from os import environ
|
|
4
|
+
|
|
5
|
+
from ncp.adapters.base import BaseAdapter
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class CohereAdapter(BaseAdapter):
|
|
9
|
+
@property
|
|
10
|
+
def ctx_window(self) -> int:
|
|
11
|
+
return 128000
|
|
12
|
+
|
|
13
|
+
def __init__(
|
|
14
|
+
self,
|
|
15
|
+
api_key: str = "",
|
|
16
|
+
model: str = "command-a-03-2025",
|
|
17
|
+
max_tokens: int = 4096,
|
|
18
|
+
timeout: float = 120.0,
|
|
19
|
+
) -> None:
|
|
20
|
+
try:
|
|
21
|
+
import cohere
|
|
22
|
+
except ImportError as err:
|
|
23
|
+
raise ImportError(
|
|
24
|
+
"cohere is required. Install it with: pip install 'ncp-sdk[providers]'"
|
|
25
|
+
) from err
|
|
26
|
+
resolved_key = api_key or environ.get("COHERE_API_KEY", "")
|
|
27
|
+
self._client = cohere.Client(
|
|
28
|
+
api_key=self._require_api_key(resolved_key, env_var="COHERE_API_KEY"),
|
|
29
|
+
timeout=timeout,
|
|
30
|
+
)
|
|
31
|
+
self._model = model
|
|
32
|
+
self._max_tokens = max_tokens
|
|
33
|
+
|
|
34
|
+
def call(self, ncp_context: str, user_turn: str) -> str:
|
|
35
|
+
from cohere.types import ChatMessage
|
|
36
|
+
|
|
37
|
+
resp = self._run_provider_call(
|
|
38
|
+
lambda: self._client.chat(
|
|
39
|
+
model=self._model,
|
|
40
|
+
max_tokens=self._max_tokens,
|
|
41
|
+
preamble=ncp_context,
|
|
42
|
+
messages=[
|
|
43
|
+
ChatMessage(role="user", message=user_turn),
|
|
44
|
+
],
|
|
45
|
+
),
|
|
46
|
+
provider="Cohere",
|
|
47
|
+
)
|
|
48
|
+
return self._coerce_text(resp.text, provider="Cohere")
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from os import environ
|
|
4
|
+
|
|
5
|
+
from ncp.adapters.base import BaseAdapter
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class GeminiAdapter(BaseAdapter):
|
|
9
|
+
@property
|
|
10
|
+
def ctx_window(self) -> int:
|
|
11
|
+
return 1000000
|
|
12
|
+
|
|
13
|
+
def __init__(
|
|
14
|
+
self,
|
|
15
|
+
api_key: str = "",
|
|
16
|
+
model: str = "gemini-2.0-flash",
|
|
17
|
+
timeout: float = 120.0,
|
|
18
|
+
) -> None:
|
|
19
|
+
try:
|
|
20
|
+
import google.generativeai as genai
|
|
21
|
+
except ImportError as err:
|
|
22
|
+
raise ImportError(
|
|
23
|
+
"google-generativeai is required. Install it with: pip install 'ncp-sdk[providers]'"
|
|
24
|
+
) from err
|
|
25
|
+
resolved_key = api_key or environ.get("GOOGLE_API_KEY", "")
|
|
26
|
+
genai.configure(api_key=self._require_api_key(resolved_key, env_var="GOOGLE_API_KEY"))
|
|
27
|
+
self._model = genai.GenerativeModel(model)
|
|
28
|
+
self._timeout = timeout
|
|
29
|
+
|
|
30
|
+
def call(self, ncp_context: str, user_turn: str) -> str:
|
|
31
|
+
prompt = f"{ncp_context}\n\n{user_turn}"
|
|
32
|
+
resp = self._run_provider_call(
|
|
33
|
+
lambda: self._model.generate_content(
|
|
34
|
+
prompt,
|
|
35
|
+
request_options={"timeout": self._timeout},
|
|
36
|
+
),
|
|
37
|
+
provider="Gemini",
|
|
38
|
+
)
|
|
39
|
+
return self._coerce_text(resp.text, provider="Gemini")
|