Python SDK and MCP server for the Intellign optimization platform — assignment, scheduling, routing, allocation, and matching problems solved via API
Project description
intellign
Python SDK + MCP server for the Intellign optimization platform — describe assignment, scheduling, routing, allocation, or matching problems and get solved rosters back. All computation runs server-side; this package is a typed HTTP client plus an MCP wrapper.
Guides: SDK guide · REST API reference · MCP server · Deployment · Examples
Install
pip install intellign # core SDK (httpx + pydantic)
pip install "intellign[mcp]" # + intellign-mcp server
pip install "intellign[pandas]" # + Result.to_dataframe()
pip install "intellign[ical]" # + Result.export_ical()
Python ≥ 3.10. Get an API key from your Intellign dashboard — ik_live_
(production) or ik_test_ (free sandbox: ≤200 entities/targets, capped
solver budget, no quota usage).
Quickstart
from intellign import Client, Problem
client = Client(
api_key="ik_live_...",
base_url="https://api.intellign.ai", # or your deployment / http://localhost:8000
)
nurses = [
{"id": "n1", "name": "Ada", "skills": "triage,general"},
{"id": "n2", "name": "Bola", "skills": "surgery"},
]
clinics = [
{"id": "c1", "name": "ER", "required_skills": "triage", "capacity": 1},
{"id": "c2", "name": "Theatre", "required_skills": "surgery", "capacity": 1},
]
problem = (
Problem.assignment(name="Nurse assignment")
.entities(rows=nurses)
.targets(rows=clinics)
.maximize("skill_match", weight=70,
entity_column="skills", target_column="required_skills")
.maximize("workload_balance", weight=30, target_column="capacity")
.require("entity.skills superset_of target.required_skills") # hard constraint
.quality("balanced") # fast | balanced | best
)
result = client.submit(problem).wait()
for a in result.assignments:
print(a["resource_id"], "->", a["target_id"])
df = result.to_dataframe() # optional pandas extra
Async — identical surface, plus SSE progress streaming:
from intellign import AsyncClient
async with AsyncClient(api_key="ik_live_...") as client:
job = await client.submit(problem)
async for event in job.stream_progress():
print(event.get("current_generation"), event.get("best_fitness"))
result = await job.result()
What you can do
| Capability | SDK entry point | Example |
|---|---|---|
| Structured solve (builder) | Problem.assignment()... → client.submit() |
examples/01 |
| Upload data once, reference by id | client.upload_dataset("team.csv") → .entities(dataset_id=...) |
examples/02 |
| Natural-language solve | client.solve_nl("assign vans to zones...", ds_a, ds_b) |
examples/03 |
| Starter templates | client.templates() / client.template(name) |
examples/04 |
| Live progress (SSE) | job.stream_progress() (sync or async) |
examples/05 |
| Webhooks on completion | client.create_webhook(url) — HMAC-signed deliveries |
examples/06 |
| Guided conversational flow | client.create_session() / send_message() / export_session() |
examples/07 |
| Robust error handling | typed exceptions, idempotency keys, retries | examples/08 |
| LLM tool access (MCP) | intellign-mcp — stdio + Streamable HTTP |
MCP guide |
Objectives & constraints
Objectives are named metrics with weights (live catalog:
client.capabilities()): skill_match, distance, workload_balance,
attribute_match, cost, preference_match — each maximize or minimize.
Constraints use a small formal grammar (invalid expressions are rejected at create time with the reason):
entity.skills superset_of target.required_skills
entity.hours <= target.max_hours # also >= == < >, or numeric literal
sum(entity.load) <= target.capacity
haversine(entity.location, target.location) <= 25
entity.region in ['north', 'east']
.require(expr) = hard (violation weight 100); .require(expr, hard=False) = soft.
Jobs & results
client.submit() returns a Job: .status(), .wait(timeout=300),
.result(), .stream_progress(). Solves are asynchronous server-side —
prefer webhooks over polling for production integrations.
Result: .assignments (list of dicts with resource_id/target_id/
score/rationale), .metrics, .best_fitness, .to_dataframe(),
.export_ical(path) for scheduling results with start/end timestamps.
Errors, retries, idempotency
Every API failure raises a typed subclass of IntelligError carrying
.code, .status_code, and .request_id (quote it in support requests):
AuthenticationError, ScopeError, InvalidSpecError, NotFoundError,
ConflictError, QuotaError, RateLimitError (.retry_after),
SandboxLimitError, SolveFailedError, ServerError.
- The client automatically retries 429/502/503/504 (honoring
Retry-After). - Pass
idempotency_key="your-uuid"tocreate_problem/solve_problem— retries return the original response instead of duplicating work (24 h window). - Rate limits per key/minute by plan: free 30, pro 120, enterprise 600.
Full error taxonomy and endpoint reference: API.md.
Webhooks
hook = client.create_webhook("https://myapp.com/hooks/intellign")
secret = hook["secret"] # shown exactly once — store it
Deliveries are POSTs with X-Intellign-Event and
X-Intellign-Signature: sha256=<hmac_sha256(secret, raw_body)>; verify with
a constant-time compare (working receiver: examples/06_webhooks.py).
Failed deliveries retry 3× and everything is inspectable via
client.webhook_deliveries(id).
MCP server
Expose Intellign as tools to Claude or any MCP client:
pip install "intellign[mcp]"
INTELLIGN_API_KEY=ik_live_... intellign-mcp # stdio (local)
intellign-mcp --transport http --port 8001 --stateless # hosted, multi-tenant
Tools: create_problem, solve_problem, get_status, get_result,
list_templates, get_template. Resources: intellign://schema/spec,
intellign://capabilities. Over HTTP each request authenticates with its
own Authorization: Bearer ik_... header.
Setup + hosting: MCP.md
and DEPLOYMENT.md.
Development
python3 -m venv .venv && .venv/bin/pip install -e ".[dev]"
.venv/bin/python -m pytest -q # unit suite (offline)
# contract tests against a live server:
INTELLIGN_CONTRACT_BASE_URL=http://localhost:8000 \
INTELLIGN_CONTRACT_API_KEY=ik_... .venv/bin/python -m pytest -m contract -q
.venv/bin/python -m build # wheel + sdist into dist/
Layout: src/intellign/ (client, spec models, builders, job/result, errors,
mcp/server.py), tests/ (unit, respx-mocked), tests/contract/
(env-gated, live server), examples/ (runnable per capability).
Releasing
CI (.github/workflows/ci.yml) tests every push/PR on Python 3.10–3.12 and
builds artifacts. Publishing (publish.yml) uses PyPI Trusted Publishing:
- Bump
src/intellign/_version.py. - Commit, tag
vX.Y.Z, push the tag. - Create a GitHub Release from the tag → workflow builds, verifies the tag
matches the package version, and publishes to PyPI via OIDC (no token
secrets). One-time setup: add this repo as a trusted publisher on
pypi.org (workflow
publish.yml, environmentpypi) and create thepypienvironment in repo settings.
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file intellign-0.1.0.tar.gz.
File metadata
- Download URL: intellign-0.1.0.tar.gz
- Upload date:
- Size: 35.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b79d67bad4b0ea8081cf00be942e526b16438da318a4e2c38c3db768bf8bd3a9
|
|
| MD5 |
de66a3093123af16c948259e7b80a539
|
|
| BLAKE2b-256 |
0ff12f1356d3d78ae3bcc305102a05236b4177f8c4943e6ce2e4a021cdfd6f2d
|
Provenance
The following attestation bundles were made for intellign-0.1.0.tar.gz:
Publisher:
publish.yml on DataBacked-Africa/intellign-python
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
intellign-0.1.0.tar.gz -
Subject digest:
b79d67bad4b0ea8081cf00be942e526b16438da318a4e2c38c3db768bf8bd3a9 - Sigstore transparency entry: 2150713333
- Sigstore integration time:
-
Permalink:
DataBacked-Africa/intellign-python@4b9ee1e3da1a6c316f8bb2426fd4522359b9d856 -
Branch / Tag:
refs/tags/0.1.0 - Owner: https://github.com/DataBacked-Africa
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@4b9ee1e3da1a6c316f8bb2426fd4522359b9d856 -
Trigger Event:
release
-
Statement type:
File details
Details for the file intellign-0.1.0-py3-none-any.whl.
File metadata
- Download URL: intellign-0.1.0-py3-none-any.whl
- Upload date:
- Size: 18.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4cbac103c71971e9f18e065759107d33cdd702fd597d7362bb9c1012a1699c52
|
|
| MD5 |
2393accfdb7c7009f1b204082da580ca
|
|
| BLAKE2b-256 |
e824c21e3c53a569a81022ba072f2ed79d458ab935132b38a6e98d12a98e5bb7
|
Provenance
The following attestation bundles were made for intellign-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on DataBacked-Africa/intellign-python
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
intellign-0.1.0-py3-none-any.whl -
Subject digest:
4cbac103c71971e9f18e065759107d33cdd702fd597d7362bb9c1012a1699c52 - Sigstore transparency entry: 2150713482
- Sigstore integration time:
-
Permalink:
DataBacked-Africa/intellign-python@4b9ee1e3da1a6c316f8bb2426fd4522359b9d856 -
Branch / Tag:
refs/tags/0.1.0 - Owner: https://github.com/DataBacked-Africa
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@4b9ee1e3da1a6c316f8bb2426fd4522359b9d856 -
Trigger Event:
release
-
Statement type: