bilinc 2.3.0__tar.gz → 2.3.3__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.
- {bilinc-2.3.0/src/bilinc.egg-info → bilinc-2.3.3}/PKG-INFO +34 -7
- {bilinc-2.3.0 → bilinc-2.3.3}/README.md +33 -6
- {bilinc-2.3.0 → bilinc-2.3.3}/pyproject.toml +1 -1
- {bilinc-2.3.0 → bilinc-2.3.3}/src/bilinc/__init__.py +2 -2
- {bilinc-2.3.0 → bilinc-2.3.3}/src/bilinc/cli/main.py +57 -11
- {bilinc-2.3.0 → bilinc-2.3.3}/src/bilinc/client.py +3 -3
- {bilinc-2.3.0 → bilinc-2.3.3/src/bilinc.egg-info}/PKG-INFO +34 -7
- {bilinc-2.3.0 → bilinc-2.3.3}/tests/test_cloud_only_package.py +68 -18
- {bilinc-2.3.0 → bilinc-2.3.3}/LICENSE +0 -0
- {bilinc-2.3.0 → bilinc-2.3.3}/MANIFEST.in +0 -0
- {bilinc-2.3.0 → bilinc-2.3.3}/setup.cfg +0 -0
- {bilinc-2.3.0 → bilinc-2.3.3}/setup.py +0 -0
- {bilinc-2.3.0 → bilinc-2.3.3}/src/bilinc/cli/__init__.py +0 -0
- {bilinc-2.3.0 → bilinc-2.3.3}/src/bilinc/cli/__main__.py +0 -0
- {bilinc-2.3.0 → bilinc-2.3.3}/src/bilinc/cli/login.py +0 -0
- {bilinc-2.3.0 → bilinc-2.3.3}/src/bilinc/cloud_mcp.py +0 -0
- {bilinc-2.3.0 → bilinc-2.3.3}/src/bilinc.egg-info/SOURCES.txt +0 -0
- {bilinc-2.3.0 → bilinc-2.3.3}/src/bilinc.egg-info/dependency_links.txt +0 -0
- {bilinc-2.3.0 → bilinc-2.3.3}/src/bilinc.egg-info/entry_points.txt +0 -0
- {bilinc-2.3.0 → bilinc-2.3.3}/src/bilinc.egg-info/requires.txt +0 -0
- {bilinc-2.3.0 → bilinc-2.3.3}/src/bilinc.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: bilinc
|
|
3
|
-
Version: 2.3.
|
|
3
|
+
Version: 2.3.3
|
|
4
4
|
Summary: Cloud-only memory SDK and MCP adapter for autonomous agents
|
|
5
5
|
Author: Bilinc Team
|
|
6
6
|
License-Expression: BUSL-1.1
|
|
@@ -56,7 +56,7 @@ Dynamic: license-file
|
|
|
56
56
|
|
|
57
57
|
Retrieval answers *"what is similar to this?"*. Long-running agents also need to answer *"who wrote this state, was it verified, did it contradict what we already knew, and can we undo it?"* — that is the layer Bilinc provides.
|
|
58
58
|
|
|
59
|
-
Bilinc 2.3.
|
|
59
|
+
Bilinc 2.3.3 on PyPI is the public cloud-only package: a thin Python SDK, CLI, and MCP adapter for Bilinc Cloud. It does not ship the local StatePlane, storage backends, eval, observability, integrations, or server runtime internals.
|
|
60
60
|
|
|
61
61
|
> **Frozen regression receipt** — LongMemEval-s cleaned retrieval fixture, 500 questions: **Hit@5 98.0%**, **NDCG@5 0.913**, no LLM reranker, no paid API. This is an isolated retrieval guardrail, not a current hosted SLA, end-to-end agent score, or competitor ranking — see [Benchmark receipt](#benchmark-receipt) for the full scope and qualification.
|
|
62
62
|
|
|
@@ -93,13 +93,30 @@ The fastest path is `pip install -U bilinc`, `bilinc login`, then `bilinc quickt
|
|
|
93
93
|
| --- | --- |
|
|
94
94
|
| A hosted memory API for an agent or MCP client | The public cloud-only package from PyPI |
|
|
95
95
|
| Local StatePlane, SQLite/PostgreSQL, benchmarks, or internals | This repository and the [architecture guide](docs/architecture.md) |
|
|
96
|
-
| A hosted MCP connection | The [MCP setup guide](https://bilinc.space/docs/mcp) |
|
|
96
|
+
| A hosted MCP connection without a Python install | The [remote MCP setup guide](https://bilinc.space/docs/remote-mcp) |
|
|
97
97
|
|
|
98
98
|
The public package is intentionally smaller than this repository. It does not bundle the internal StatePlane or local
|
|
99
99
|
storage runtime.
|
|
100
100
|
|
|
101
101
|
## Start in 60 Seconds
|
|
102
102
|
|
|
103
|
+
### Claude connector, without installing Python
|
|
104
|
+
|
|
105
|
+
Open **Customize → Connectors → Add custom connector** in Claude, name it Bilinc,
|
|
106
|
+
and paste `https://mcp.bilinc.space/mcp`. Sign in and choose read-only or read and
|
|
107
|
+
write access. The setup guide is [bilinc.space/mcp](https://bilinc.space/mcp).
|
|
108
|
+
|
|
109
|
+
For the remote connector in Claude Code:
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
claude mcp add --transport http --scope user bilinc https://mcp.bilinc.space/mcp
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Then run `/mcp` and authenticate. The remote connector has ten tools; the Python
|
|
116
|
+
stdio adapter below has eight. Both connect to hosted Bilinc memory.
|
|
117
|
+
|
|
118
|
+
### SDK and CLI
|
|
119
|
+
|
|
103
120
|
```bash
|
|
104
121
|
pip install -U bilinc
|
|
105
122
|
bilinc login
|
|
@@ -119,7 +136,7 @@ Cloud status check.
|
|
|
119
136
|
To reproduce this release exactly:
|
|
120
137
|
|
|
121
138
|
```bash
|
|
122
|
-
pip install -U bilinc==2.3.
|
|
139
|
+
pip install -U bilinc==2.3.3
|
|
123
140
|
```
|
|
124
141
|
|
|
125
142
|
If you prefer a browser guide, open https://bilinc.space/install and follow the
|
|
@@ -131,18 +148,28 @@ Bilinc exposes a standard Model Context Protocol server over **stdio**, so any
|
|
|
131
148
|
MCP-compatible client can connect — Claude Code, Codex, Cursor, Hermes-Agent,
|
|
132
149
|
opencode, and others.
|
|
133
150
|
|
|
151
|
+
After `bilinc login`, let the CLI write the setup for your client:
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
bilinc mcp install --client claude-code # prints a ready `claude mcp add ...` command
|
|
155
|
+
bilinc mcp install --client claude-desktop # prints the config and where Claude Desktop keeps it
|
|
156
|
+
bilinc mcp install # plain mcpServers JSON for any other client
|
|
157
|
+
```
|
|
158
|
+
|
|
134
159
|
```json
|
|
135
160
|
{
|
|
136
161
|
"mcpServers": {
|
|
137
162
|
"bilinc": {
|
|
138
|
-
"command": "
|
|
139
|
-
"args": ["-m", "bilinc.cloud_mcp"]
|
|
140
|
-
"env": { "BILINC_API_KEY": "bil_live_..." }
|
|
163
|
+
"command": "/path/to/python3",
|
|
164
|
+
"args": ["-m", "bilinc.cloud_mcp"]
|
|
141
165
|
}
|
|
142
166
|
}
|
|
143
167
|
}
|
|
144
168
|
```
|
|
145
169
|
|
|
170
|
+
`command` is the interpreter that has Bilinc installed, and the adapter reads the key saved by `bilinc login`, so
|
|
171
|
+
the config carries no key. On a machine without a saved key, add `"env": { "BILINC_API_KEY": "bil_live_..." }`.
|
|
172
|
+
|
|
146
173
|
Eight tools — the core memory lifecycle, and nothing else:
|
|
147
174
|
|
|
148
175
|
| Tool | What it does |
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
Retrieval answers *"what is similar to this?"*. Long-running agents also need to answer *"who wrote this state, was it verified, did it contradict what we already knew, and can we undo it?"* — that is the layer Bilinc provides.
|
|
16
16
|
|
|
17
|
-
Bilinc 2.3.
|
|
17
|
+
Bilinc 2.3.3 on PyPI is the public cloud-only package: a thin Python SDK, CLI, and MCP adapter for Bilinc Cloud. It does not ship the local StatePlane, storage backends, eval, observability, integrations, or server runtime internals.
|
|
18
18
|
|
|
19
19
|
> **Frozen regression receipt** — LongMemEval-s cleaned retrieval fixture, 500 questions: **Hit@5 98.0%**, **NDCG@5 0.913**, no LLM reranker, no paid API. This is an isolated retrieval guardrail, not a current hosted SLA, end-to-end agent score, or competitor ranking — see [Benchmark receipt](#benchmark-receipt) for the full scope and qualification.
|
|
20
20
|
|
|
@@ -51,13 +51,30 @@ The fastest path is `pip install -U bilinc`, `bilinc login`, then `bilinc quickt
|
|
|
51
51
|
| --- | --- |
|
|
52
52
|
| A hosted memory API for an agent or MCP client | The public cloud-only package from PyPI |
|
|
53
53
|
| Local StatePlane, SQLite/PostgreSQL, benchmarks, or internals | This repository and the [architecture guide](docs/architecture.md) |
|
|
54
|
-
| A hosted MCP connection | The [MCP setup guide](https://bilinc.space/docs/mcp) |
|
|
54
|
+
| A hosted MCP connection without a Python install | The [remote MCP setup guide](https://bilinc.space/docs/remote-mcp) |
|
|
55
55
|
|
|
56
56
|
The public package is intentionally smaller than this repository. It does not bundle the internal StatePlane or local
|
|
57
57
|
storage runtime.
|
|
58
58
|
|
|
59
59
|
## Start in 60 Seconds
|
|
60
60
|
|
|
61
|
+
### Claude connector, without installing Python
|
|
62
|
+
|
|
63
|
+
Open **Customize → Connectors → Add custom connector** in Claude, name it Bilinc,
|
|
64
|
+
and paste `https://mcp.bilinc.space/mcp`. Sign in and choose read-only or read and
|
|
65
|
+
write access. The setup guide is [bilinc.space/mcp](https://bilinc.space/mcp).
|
|
66
|
+
|
|
67
|
+
For the remote connector in Claude Code:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
claude mcp add --transport http --scope user bilinc https://mcp.bilinc.space/mcp
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Then run `/mcp` and authenticate. The remote connector has ten tools; the Python
|
|
74
|
+
stdio adapter below has eight. Both connect to hosted Bilinc memory.
|
|
75
|
+
|
|
76
|
+
### SDK and CLI
|
|
77
|
+
|
|
61
78
|
```bash
|
|
62
79
|
pip install -U bilinc
|
|
63
80
|
bilinc login
|
|
@@ -77,7 +94,7 @@ Cloud status check.
|
|
|
77
94
|
To reproduce this release exactly:
|
|
78
95
|
|
|
79
96
|
```bash
|
|
80
|
-
pip install -U bilinc==2.3.
|
|
97
|
+
pip install -U bilinc==2.3.3
|
|
81
98
|
```
|
|
82
99
|
|
|
83
100
|
If you prefer a browser guide, open https://bilinc.space/install and follow the
|
|
@@ -89,18 +106,28 @@ Bilinc exposes a standard Model Context Protocol server over **stdio**, so any
|
|
|
89
106
|
MCP-compatible client can connect — Claude Code, Codex, Cursor, Hermes-Agent,
|
|
90
107
|
opencode, and others.
|
|
91
108
|
|
|
109
|
+
After `bilinc login`, let the CLI write the setup for your client:
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
bilinc mcp install --client claude-code # prints a ready `claude mcp add ...` command
|
|
113
|
+
bilinc mcp install --client claude-desktop # prints the config and where Claude Desktop keeps it
|
|
114
|
+
bilinc mcp install # plain mcpServers JSON for any other client
|
|
115
|
+
```
|
|
116
|
+
|
|
92
117
|
```json
|
|
93
118
|
{
|
|
94
119
|
"mcpServers": {
|
|
95
120
|
"bilinc": {
|
|
96
|
-
"command": "
|
|
97
|
-
"args": ["-m", "bilinc.cloud_mcp"]
|
|
98
|
-
"env": { "BILINC_API_KEY": "bil_live_..." }
|
|
121
|
+
"command": "/path/to/python3",
|
|
122
|
+
"args": ["-m", "bilinc.cloud_mcp"]
|
|
99
123
|
}
|
|
100
124
|
}
|
|
101
125
|
}
|
|
102
126
|
```
|
|
103
127
|
|
|
128
|
+
`command` is the interpreter that has Bilinc installed, and the adapter reads the key saved by `bilinc login`, so
|
|
129
|
+
the config carries no key. On a machine without a saved key, add `"env": { "BILINC_API_KEY": "bil_live_..." }`.
|
|
130
|
+
|
|
104
131
|
Eight tools — the core memory lifecycle, and nothing else:
|
|
105
132
|
|
|
106
133
|
| Tool | What it does |
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""Bilinc 2.3.
|
|
1
|
+
"""Bilinc 2.3.3: cloud-only SDK for agent memory."""
|
|
2
2
|
|
|
3
3
|
from bilinc.client import (
|
|
4
4
|
ACTIVATION_SIGNUP_URL,
|
|
@@ -25,7 +25,7 @@ from bilinc.client import (
|
|
|
25
25
|
CloudClient,
|
|
26
26
|
)
|
|
27
27
|
|
|
28
|
-
__version__ = "2.3.
|
|
28
|
+
__version__ = "2.3.3"
|
|
29
29
|
version = __version__
|
|
30
30
|
|
|
31
31
|
__all__ = [
|
|
@@ -6,6 +6,8 @@ from __future__ import annotations
|
|
|
6
6
|
import argparse
|
|
7
7
|
import json
|
|
8
8
|
import os
|
|
9
|
+
import shlex
|
|
10
|
+
import subprocess
|
|
9
11
|
import sys
|
|
10
12
|
import time
|
|
11
13
|
import webbrowser
|
|
@@ -64,16 +66,38 @@ def _print_start_guide(*, opened: bool = False) -> None:
|
|
|
64
66
|
)
|
|
65
67
|
|
|
66
68
|
|
|
69
|
+
MCP_KEY_PLACEHOLDER = "bil_live_..."
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def _mcp_server_entry() -> dict[str, Any]:
|
|
73
|
+
# The absolute interpreter works where a bare `python` does not: macOS ships
|
|
74
|
+
# only python3, and Claude Desktop launches servers without the shell PATH.
|
|
75
|
+
entry: dict[str, Any] = {"command": sys.executable, "args": ["-m", "bilinc.cloud_mcp"]}
|
|
76
|
+
if not load_config_api_key():
|
|
77
|
+
# With a key saved by `bilinc login` the adapter reads it itself, so the
|
|
78
|
+
# client config carries no key at all. Without one, the client must pass it.
|
|
79
|
+
entry["env"] = {"BILINC_API_KEY": MCP_KEY_PLACEHOLDER}
|
|
80
|
+
return entry
|
|
81
|
+
|
|
82
|
+
|
|
67
83
|
def _mcp_config() -> dict[str, Any]:
|
|
68
|
-
return {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
84
|
+
return {"mcpServers": {"bilinc": _mcp_server_entry()}}
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def _claude_code_command() -> str:
|
|
88
|
+
argv = ["claude", "mcp", "add", "--scope", "user", "bilinc"]
|
|
89
|
+
if not load_config_api_key():
|
|
90
|
+
argv += ["-e", f"BILINC_API_KEY={MCP_KEY_PLACEHOLDER}"]
|
|
91
|
+
argv += ["--", sys.executable, "-m", "bilinc.cloud_mcp"]
|
|
92
|
+
return subprocess.list2cmdline(argv) if os.name == "nt" else shlex.join(argv)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def _claude_desktop_config_path() -> str:
|
|
96
|
+
if sys.platform == "darwin":
|
|
97
|
+
return "~/Library/Application Support/Claude/claude_desktop_config.json"
|
|
98
|
+
if os.name == "nt":
|
|
99
|
+
return r"%APPDATA%\Claude\claude_desktop_config.json"
|
|
100
|
+
return "~/.config/Claude/claude_desktop_config.json"
|
|
77
101
|
|
|
78
102
|
|
|
79
103
|
def build_parser() -> argparse.ArgumentParser:
|
|
@@ -174,7 +198,14 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
174
198
|
|
|
175
199
|
mcp = sub.add_parser("mcp", help="Print hosted Cloud MCP adapter configuration")
|
|
176
200
|
mcp_sub = mcp.add_subparsers(dest="mcp_command")
|
|
177
|
-
mcp_sub.add_parser("install", help="Print MCP config for agent runtimes")
|
|
201
|
+
mcp_install = mcp_sub.add_parser("install", help="Print MCP config for agent runtimes")
|
|
202
|
+
mcp_install.add_argument(
|
|
203
|
+
"--client",
|
|
204
|
+
choices=["json", "claude-code", "claude-desktop"],
|
|
205
|
+
default="json",
|
|
206
|
+
help="json: mcpServers config (default); claude-code: a `claude mcp add` command; "
|
|
207
|
+
"claude-desktop: the config plus where Claude Desktop keeps it",
|
|
208
|
+
)
|
|
178
209
|
|
|
179
210
|
sub.add_parser("signup", help="Print the signup URL (free, no card required)")
|
|
180
211
|
|
|
@@ -252,7 +283,22 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
252
283
|
)
|
|
253
284
|
return 0
|
|
254
285
|
if args.command == "mcp" and args.mcp_command == "install":
|
|
255
|
-
|
|
286
|
+
# stdout stays copy-paste clean; guidance goes to stderr.
|
|
287
|
+
if args.client == "claude-code":
|
|
288
|
+
print(_claude_code_command())
|
|
289
|
+
else:
|
|
290
|
+
_print(_mcp_config())
|
|
291
|
+
if args.client == "claude-desktop":
|
|
292
|
+
print(
|
|
293
|
+
f'Merge the "bilinc" entry into mcpServers in {_claude_desktop_config_path()}, '
|
|
294
|
+
"then restart Claude Desktop.",
|
|
295
|
+
file=sys.stderr,
|
|
296
|
+
)
|
|
297
|
+
if not load_config_api_key():
|
|
298
|
+
print(
|
|
299
|
+
f"No saved key yet: run `bilinc login` first, or replace {MCP_KEY_PLACEHOLDER} with your API key.",
|
|
300
|
+
file=sys.stderr,
|
|
301
|
+
)
|
|
256
302
|
return 0
|
|
257
303
|
if args.command is None:
|
|
258
304
|
parser.print_help()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""Bilinc Cloud client.
|
|
2
2
|
|
|
3
|
-
Bilinc 2.3.
|
|
3
|
+
Bilinc 2.3.3 is cloud-only: the PyPI package is a thin SDK and MCP adapter for
|
|
4
4
|
https://bilinc.space. Local self-hosted StatePlane internals are no longer
|
|
5
5
|
shipped in the public package.
|
|
6
6
|
"""
|
|
@@ -18,10 +18,10 @@ from dataclasses import dataclass
|
|
|
18
18
|
from pathlib import Path
|
|
19
19
|
from typing import Any, Callable
|
|
20
20
|
|
|
21
|
-
__version__ = "2.3.
|
|
21
|
+
__version__ = "2.3.3"
|
|
22
22
|
DEFAULT_BASE_URL = "https://bilinc.space"
|
|
23
23
|
SIGNUP_URL = "https://bilinc.space/signup"
|
|
24
|
-
ACTIVATION_CAMPAIGN = "
|
|
24
|
+
ACTIVATION_CAMPAIGN = "activation_2_3_3"
|
|
25
25
|
ACTIVATION_SIGNUP_URL = (
|
|
26
26
|
f"{SIGNUP_URL}?utm_source=pypi&utm_medium=cli&utm_campaign={ACTIVATION_CAMPAIGN}"
|
|
27
27
|
)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: bilinc
|
|
3
|
-
Version: 2.3.
|
|
3
|
+
Version: 2.3.3
|
|
4
4
|
Summary: Cloud-only memory SDK and MCP adapter for autonomous agents
|
|
5
5
|
Author: Bilinc Team
|
|
6
6
|
License-Expression: BUSL-1.1
|
|
@@ -56,7 +56,7 @@ Dynamic: license-file
|
|
|
56
56
|
|
|
57
57
|
Retrieval answers *"what is similar to this?"*. Long-running agents also need to answer *"who wrote this state, was it verified, did it contradict what we already knew, and can we undo it?"* — that is the layer Bilinc provides.
|
|
58
58
|
|
|
59
|
-
Bilinc 2.3.
|
|
59
|
+
Bilinc 2.3.3 on PyPI is the public cloud-only package: a thin Python SDK, CLI, and MCP adapter for Bilinc Cloud. It does not ship the local StatePlane, storage backends, eval, observability, integrations, or server runtime internals.
|
|
60
60
|
|
|
61
61
|
> **Frozen regression receipt** — LongMemEval-s cleaned retrieval fixture, 500 questions: **Hit@5 98.0%**, **NDCG@5 0.913**, no LLM reranker, no paid API. This is an isolated retrieval guardrail, not a current hosted SLA, end-to-end agent score, or competitor ranking — see [Benchmark receipt](#benchmark-receipt) for the full scope and qualification.
|
|
62
62
|
|
|
@@ -93,13 +93,30 @@ The fastest path is `pip install -U bilinc`, `bilinc login`, then `bilinc quickt
|
|
|
93
93
|
| --- | --- |
|
|
94
94
|
| A hosted memory API for an agent or MCP client | The public cloud-only package from PyPI |
|
|
95
95
|
| Local StatePlane, SQLite/PostgreSQL, benchmarks, or internals | This repository and the [architecture guide](docs/architecture.md) |
|
|
96
|
-
| A hosted MCP connection | The [MCP setup guide](https://bilinc.space/docs/mcp) |
|
|
96
|
+
| A hosted MCP connection without a Python install | The [remote MCP setup guide](https://bilinc.space/docs/remote-mcp) |
|
|
97
97
|
|
|
98
98
|
The public package is intentionally smaller than this repository. It does not bundle the internal StatePlane or local
|
|
99
99
|
storage runtime.
|
|
100
100
|
|
|
101
101
|
## Start in 60 Seconds
|
|
102
102
|
|
|
103
|
+
### Claude connector, without installing Python
|
|
104
|
+
|
|
105
|
+
Open **Customize → Connectors → Add custom connector** in Claude, name it Bilinc,
|
|
106
|
+
and paste `https://mcp.bilinc.space/mcp`. Sign in and choose read-only or read and
|
|
107
|
+
write access. The setup guide is [bilinc.space/mcp](https://bilinc.space/mcp).
|
|
108
|
+
|
|
109
|
+
For the remote connector in Claude Code:
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
claude mcp add --transport http --scope user bilinc https://mcp.bilinc.space/mcp
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Then run `/mcp` and authenticate. The remote connector has ten tools; the Python
|
|
116
|
+
stdio adapter below has eight. Both connect to hosted Bilinc memory.
|
|
117
|
+
|
|
118
|
+
### SDK and CLI
|
|
119
|
+
|
|
103
120
|
```bash
|
|
104
121
|
pip install -U bilinc
|
|
105
122
|
bilinc login
|
|
@@ -119,7 +136,7 @@ Cloud status check.
|
|
|
119
136
|
To reproduce this release exactly:
|
|
120
137
|
|
|
121
138
|
```bash
|
|
122
|
-
pip install -U bilinc==2.3.
|
|
139
|
+
pip install -U bilinc==2.3.3
|
|
123
140
|
```
|
|
124
141
|
|
|
125
142
|
If you prefer a browser guide, open https://bilinc.space/install and follow the
|
|
@@ -131,18 +148,28 @@ Bilinc exposes a standard Model Context Protocol server over **stdio**, so any
|
|
|
131
148
|
MCP-compatible client can connect — Claude Code, Codex, Cursor, Hermes-Agent,
|
|
132
149
|
opencode, and others.
|
|
133
150
|
|
|
151
|
+
After `bilinc login`, let the CLI write the setup for your client:
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
bilinc mcp install --client claude-code # prints a ready `claude mcp add ...` command
|
|
155
|
+
bilinc mcp install --client claude-desktop # prints the config and where Claude Desktop keeps it
|
|
156
|
+
bilinc mcp install # plain mcpServers JSON for any other client
|
|
157
|
+
```
|
|
158
|
+
|
|
134
159
|
```json
|
|
135
160
|
{
|
|
136
161
|
"mcpServers": {
|
|
137
162
|
"bilinc": {
|
|
138
|
-
"command": "
|
|
139
|
-
"args": ["-m", "bilinc.cloud_mcp"]
|
|
140
|
-
"env": { "BILINC_API_KEY": "bil_live_..." }
|
|
163
|
+
"command": "/path/to/python3",
|
|
164
|
+
"args": ["-m", "bilinc.cloud_mcp"]
|
|
141
165
|
}
|
|
142
166
|
}
|
|
143
167
|
}
|
|
144
168
|
```
|
|
145
169
|
|
|
170
|
+
`command` is the interpreter that has Bilinc installed, and the adapter reads the key saved by `bilinc login`, so
|
|
171
|
+
the config carries no key. On a machine without a saved key, add `"env": { "BILINC_API_KEY": "bil_live_..." }`.
|
|
172
|
+
|
|
146
173
|
Eight tools — the core memory lifecycle, and nothing else:
|
|
147
174
|
|
|
148
175
|
| Tool | What it does |
|
|
@@ -12,9 +12,9 @@ import pytest
|
|
|
12
12
|
def test_public_api_is_cloud_only():
|
|
13
13
|
import bilinc
|
|
14
14
|
|
|
15
|
-
assert bilinc.__version__ == "2.3.
|
|
16
|
-
assert bilinc.version == "2.3.
|
|
17
|
-
assert "utm_campaign=
|
|
15
|
+
assert bilinc.__version__ == "2.3.3"
|
|
16
|
+
assert bilinc.version == "2.3.3"
|
|
17
|
+
assert "utm_campaign=activation_2_3_3" in bilinc.ACTIVATION_SIGNUP_URL
|
|
18
18
|
assert hasattr(bilinc, "Bilinc")
|
|
19
19
|
assert hasattr(bilinc, "CloudClient")
|
|
20
20
|
assert not hasattr(bilinc, "StatePlane")
|
|
@@ -75,7 +75,7 @@ def test_cloud_client_normalizes_base_url():
|
|
|
75
75
|
from bilinc import CloudClient
|
|
76
76
|
|
|
77
77
|
transport = RecordingTransport({"status": "ok"})
|
|
78
|
-
client = CloudClient(api_key="
|
|
78
|
+
client = CloudClient(api_key="bil_live_example", base_url="https://bilinc.space///", transport=transport)
|
|
79
79
|
|
|
80
80
|
client.status()
|
|
81
81
|
|
|
@@ -87,7 +87,7 @@ def test_cloud_client_base_url_can_come_from_env(monkeypatch):
|
|
|
87
87
|
|
|
88
88
|
monkeypatch.setenv("BILINC_BASE_URL", "http://127.0.0.1:9999/")
|
|
89
89
|
transport = RecordingTransport({"status": "ok"})
|
|
90
|
-
client = CloudClient(api_key="
|
|
90
|
+
client = CloudClient(api_key="bil_live_example", transport=transport)
|
|
91
91
|
|
|
92
92
|
client.status()
|
|
93
93
|
|
|
@@ -98,7 +98,7 @@ def test_cloud_client_commit_posts_to_hosted_api():
|
|
|
98
98
|
from bilinc import CloudClient
|
|
99
99
|
|
|
100
100
|
transport = RecordingTransport({"success": True, "id": "mem_123"})
|
|
101
|
-
client = CloudClient(api_key="
|
|
101
|
+
client = CloudClient(api_key="bil_live_example", base_url="https://bilinc.space", transport=transport)
|
|
102
102
|
|
|
103
103
|
result = client.commit("project.status", {"phase": "trial"}, memory_type="semantic", importance=0.8)
|
|
104
104
|
|
|
@@ -108,11 +108,11 @@ def test_cloud_client_commit_posts_to_hosted_api():
|
|
|
108
108
|
"method": "POST",
|
|
109
109
|
"url": "https://bilinc.space/api/cloud/memory/commit",
|
|
110
110
|
"headers": {
|
|
111
|
-
"Authorization": "Bearer
|
|
111
|
+
"Authorization": "Bearer bil_live_example",
|
|
112
112
|
"Content-Type": "application/json",
|
|
113
|
-
"User-Agent": "bilinc-python/2.3.
|
|
113
|
+
"User-Agent": "bilinc-python/2.3.3",
|
|
114
114
|
"X-Bilinc-Client": "python-sdk",
|
|
115
|
-
"X-Bilinc-Client-Version": "2.3.
|
|
115
|
+
"X-Bilinc-Client-Version": "2.3.3",
|
|
116
116
|
},
|
|
117
117
|
"body": json.dumps(
|
|
118
118
|
{
|
|
@@ -133,7 +133,7 @@ def test_cloud_client_recall_posts_to_hosted_api():
|
|
|
133
133
|
from bilinc import CloudClient
|
|
134
134
|
|
|
135
135
|
transport = RecordingTransport({"results": [{"key": "project.status"}]})
|
|
136
|
-
client = CloudClient(api_key="
|
|
136
|
+
client = CloudClient(api_key="bil_live_example", transport=transport)
|
|
137
137
|
|
|
138
138
|
result = client.recall("trial status", profile="balanced", limit=5)
|
|
139
139
|
|
|
@@ -148,7 +148,7 @@ def test_cloud_client_recall_forwards_point_in_time_timestamp():
|
|
|
148
148
|
from bilinc import CloudClient
|
|
149
149
|
|
|
150
150
|
transport = RecordingTransport({"results": []})
|
|
151
|
-
client = CloudClient(api_key="
|
|
151
|
+
client = CloudClient(api_key="bil_live_example", transport=transport)
|
|
152
152
|
|
|
153
153
|
client.recall(
|
|
154
154
|
"deployment target",
|
|
@@ -167,7 +167,7 @@ def test_cloud_client_recall_forwards_point_in_time_timestamp():
|
|
|
167
167
|
def test_cloud_client_rejects_an_unbounded_point_in_time_timestamp():
|
|
168
168
|
from bilinc import BilincValidationError, CloudClient
|
|
169
169
|
|
|
170
|
-
client = CloudClient(api_key="
|
|
170
|
+
client = CloudClient(api_key="bil_live_example", transport=RecordingTransport({}))
|
|
171
171
|
|
|
172
172
|
with pytest.raises(BilincValidationError, match="query_timestamp"):
|
|
173
173
|
client.recall("q", query_timestamp="x" * 65)
|
|
@@ -177,7 +177,7 @@ def test_cloud_client_status_reads_the_authenticated_status_endpoint():
|
|
|
177
177
|
from bilinc import CloudClient
|
|
178
178
|
|
|
179
179
|
transport = RecordingTransport({"status": "ok", "plan": {"key": "pro"}})
|
|
180
|
-
client = CloudClient(api_key="
|
|
180
|
+
client = CloudClient(api_key="bil_live_example", transport=transport)
|
|
181
181
|
|
|
182
182
|
result = client.status()
|
|
183
183
|
|
|
@@ -187,8 +187,8 @@ def test_cloud_client_status_reads_the_authenticated_status_endpoint():
|
|
|
187
187
|
"method": "GET",
|
|
188
188
|
"url": "https://bilinc.space/api/cloud/status",
|
|
189
189
|
"headers": {
|
|
190
|
-
"Authorization": "Bearer
|
|
191
|
-
"User-Agent": "bilinc-python/2.3.
|
|
190
|
+
"Authorization": "Bearer bil_live_example",
|
|
191
|
+
"User-Agent": "bilinc-python/2.3.3",
|
|
192
192
|
},
|
|
193
193
|
"body": None,
|
|
194
194
|
"timeout": 30.0,
|
|
@@ -200,7 +200,7 @@ def test_cloud_client_health_stays_on_the_public_service_endpoint():
|
|
|
200
200
|
from bilinc import CloudClient
|
|
201
201
|
|
|
202
202
|
transport = RecordingTransport({"status": "ok", "mode": "live_cloud"})
|
|
203
|
-
client = CloudClient(api_key="
|
|
203
|
+
client = CloudClient(api_key="bil_live_example", transport=transport)
|
|
204
204
|
|
|
205
205
|
result = client.health()
|
|
206
206
|
|
|
@@ -261,7 +261,7 @@ def test_cli_signup_and_missing_key_failure(monkeypatch, capsys):
|
|
|
261
261
|
assert main(["signup"]) == 0
|
|
262
262
|
signup_out = capsys.readouterr()
|
|
263
263
|
assert "https://bilinc.space/signup" in signup_out.out
|
|
264
|
-
assert "
|
|
264
|
+
assert "activation_2_3_3" in signup_out.out
|
|
265
265
|
assert "quicktest" in signup_out.out
|
|
266
266
|
|
|
267
267
|
assert main(["commit", "--key", "smoke_key", "--value", "hello"]) == 1
|
|
@@ -305,7 +305,7 @@ def test_cli_start_login_doctor_quicktest_and_mcp_config(monkeypatch, capsys, tm
|
|
|
305
305
|
assert "bilinc login --api-key <key>" in start_out.out
|
|
306
306
|
assert "bilinc quicktest" in start_out.out
|
|
307
307
|
assert "install_guide" in start_out.out
|
|
308
|
-
assert "
|
|
308
|
+
assert "activation_2_3_3" in start_out.out
|
|
309
309
|
|
|
310
310
|
assert cli_main.main(["login", "--api-key", "bil_live_cli_test"]) == 0
|
|
311
311
|
login_out = capsys.readouterr()
|
|
@@ -327,6 +327,56 @@ def test_cli_start_login_doctor_quicktest_and_mcp_config(monkeypatch, capsys, tm
|
|
|
327
327
|
assert "bil_live_cli_test" not in mcp_out.out
|
|
328
328
|
|
|
329
329
|
|
|
330
|
+
def test_mcp_install_uses_the_login_key_and_a_real_interpreter(monkeypatch, capsys, tmp_path):
|
|
331
|
+
import sys
|
|
332
|
+
|
|
333
|
+
from bilinc.cli import main as cli_main
|
|
334
|
+
|
|
335
|
+
monkeypatch.delenv("BILINC_API_KEY", raising=False)
|
|
336
|
+
monkeypatch.setenv("BILINC_CONFIG_DIR", str(tmp_path))
|
|
337
|
+
assert cli_main.main(["login", "--api-key", "bil_live_saved_key"]) == 0
|
|
338
|
+
capsys.readouterr()
|
|
339
|
+
|
|
340
|
+
# Default JSON: absolute interpreter, and no env block — the adapter reads the saved key.
|
|
341
|
+
assert cli_main.main(["mcp", "install"]) == 0
|
|
342
|
+
out = capsys.readouterr()
|
|
343
|
+
server = json.loads(out.out)["mcpServers"]["bilinc"]
|
|
344
|
+
assert server == {"command": sys.executable, "args": ["-m", "bilinc.cloud_mcp"]}
|
|
345
|
+
assert "bil_live_saved_key" not in out.out + out.err
|
|
346
|
+
assert "${BILINC_API_KEY}" not in out.out
|
|
347
|
+
|
|
348
|
+
# Claude Code: one runnable command, user scope, no key on the command line.
|
|
349
|
+
assert cli_main.main(["mcp", "install", "--client", "claude-code"]) == 0
|
|
350
|
+
out = capsys.readouterr()
|
|
351
|
+
assert out.out.startswith("claude mcp add --scope user bilinc -- ")
|
|
352
|
+
assert out.out.rstrip().endswith("-m bilinc.cloud_mcp")
|
|
353
|
+
assert "BILINC_API_KEY" not in out.out
|
|
354
|
+
assert "bil_live_saved_key" not in out.out + out.err
|
|
355
|
+
|
|
356
|
+
# Claude Desktop: clean JSON on stdout, the config location on stderr.
|
|
357
|
+
assert cli_main.main(["mcp", "install", "--client", "claude-desktop"]) == 0
|
|
358
|
+
out = capsys.readouterr()
|
|
359
|
+
assert json.loads(out.out)["mcpServers"]["bilinc"]["command"] == sys.executable
|
|
360
|
+
assert "claude_desktop_config.json" in out.err
|
|
361
|
+
assert "bil_live_saved_key" not in out.out + out.err
|
|
362
|
+
|
|
363
|
+
|
|
364
|
+
def test_mcp_install_without_a_saved_key_asks_for_one(monkeypatch, capsys, tmp_path):
|
|
365
|
+
from bilinc.cli import main as cli_main
|
|
366
|
+
|
|
367
|
+
monkeypatch.delenv("BILINC_API_KEY", raising=False)
|
|
368
|
+
monkeypatch.setenv("BILINC_CONFIG_DIR", str(tmp_path))
|
|
369
|
+
|
|
370
|
+
assert cli_main.main(["mcp", "install"]) == 0
|
|
371
|
+
out = capsys.readouterr()
|
|
372
|
+
assert json.loads(out.out)["mcpServers"]["bilinc"]["env"] == {"BILINC_API_KEY": "bil_live_..."}
|
|
373
|
+
assert "bilinc login" in out.err
|
|
374
|
+
|
|
375
|
+
assert cli_main.main(["mcp", "install", "--client", "claude-code"]) == 0
|
|
376
|
+
out = capsys.readouterr()
|
|
377
|
+
assert "-e BILINC_API_KEY=bil_live_..." in out.out
|
|
378
|
+
|
|
379
|
+
|
|
330
380
|
def _forbidden_package_prefixes(root: str = "") -> tuple[str, ...]:
|
|
331
381
|
return tuple(
|
|
332
382
|
f"{root}{prefix}"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|