Metadata-Version: 2.4
Name: thingctx
Version: 0.2.1
Summary: Drive any agent against any W3C WoT Thing, over any transport. No per-integration server.
Author: The thingctx Authors
License: Apache-2.0
Project-URL: Homepage, https://thingctx.com
Project-URL: Repository, https://github.com/thingctx/thingctx
Keywords: llm,wot,web-of-things,thing-description,mcp,tool-calling,agents
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: License :: OSI Approved :: Apache Software License
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
License-File: NOTICE
Provides-Extra: llm
Requires-Dist: litellm>=1.0; extra == "llm"
Provides-Extra: http
Requires-Dist: httpx>=0.25; extra == "http"
Provides-Extra: mqtt
Requires-Dist: paho-mqtt>=2.0; extra == "mqtt"
Provides-Extra: validate
Requires-Dist: jsonschema>=4.0; extra == "validate"
Provides-Extra: mcp
Requires-Dist: mcp>=1.3; extra == "mcp"
Provides-Extra: mcp-http
Requires-Dist: mcp>=1.3; extra == "mcp-http"
Requires-Dist: uvicorn>=0.27; extra == "mcp-http"
Provides-Extra: openapi
Requires-Dist: httpx>=0.25; extra == "openapi"
Requires-Dist: pyyaml>=6; extra == "openapi"
Provides-Extra: cloud
Requires-Dist: httpx>=0.25; extra == "cloud"
Requires-Dist: pyjwt[crypto]>=2.8; extra == "cloud"
Provides-Extra: media
Requires-Dist: av>=11; extra == "media"
Requires-Dist: numpy>=1.23; extra == "media"
Requires-Dist: pillow>=10; extra == "media"
Provides-Extra: authz
Requires-Dist: pyjwt[crypto]>=2.8; extra == "authz"
Requires-Dist: httpx>=0.27; extra == "authz"
Provides-Extra: entra
Requires-Dist: azure-identity>=1.20; extra == "entra"
Requires-Dist: pyjwt[crypto]>=2.8; extra == "entra"
Requires-Dist: httpx>=0.27; extra == "entra"
Provides-Extra: filesystem
Provides-Extra: all
Requires-Dist: litellm>=1.0; extra == "all"
Requires-Dist: httpx>=0.27; extra == "all"
Requires-Dist: paho-mqtt>=2.0; extra == "all"
Requires-Dist: jsonschema>=4.0; extra == "all"
Requires-Dist: mcp>=1.3; extra == "all"
Requires-Dist: pyyaml>=6; extra == "all"
Requires-Dist: pyjwt[crypto]>=2.8; extra == "all"
Requires-Dist: azure-identity>=1.20; extra == "all"
Requires-Dist: av>=11; extra == "all"
Requires-Dist: numpy>=1.23; extra == "all"
Requires-Dist: pillow>=10; extra == "all"
Provides-Extra: dev
Requires-Dist: pytest>=7; extra == "dev"
Requires-Dist: pytest-asyncio>=0.21; extra == "dev"
Requires-Dist: pytest-cov==7.1.0; extra == "dev"
Requires-Dist: jsonschema>=4.0; extra == "dev"
Requires-Dist: mcp>=1.3; extra == "dev"
Requires-Dist: httpx>=0.27; extra == "dev"
Requires-Dist: pyyaml>=6; extra == "dev"
Requires-Dist: pyjwt[crypto]>=2.8; extra == "dev"
Requires-Dist: azure-identity>=1.20; extra == "dev"
Requires-Dist: paho-mqtt>=2.0; extra == "dev"
Requires-Dist: av>=11; extra == "dev"
Requires-Dist: numpy>=1.23; extra == "dev"
Requires-Dist: pillow>=10; extra == "dev"
Requires-Dist: botocore>=1.34; extra == "dev"
Requires-Dist: ruff==0.16.0; extra == "dev"
Requires-Dist: mypy==2.3.0; extra == "dev"
Requires-Dist: vulture==2.16; extra == "dev"
Requires-Dist: bandit==1.9.4; extra == "dev"
Requires-Dist: pip-audit==2.10.1; extra == "dev"
Requires-Dist: import-linter==2.13; extra == "dev"
Requires-Dist: diff-cover==10.4.1; extra == "dev"
Dynamic: license-file

# thingctx

thingctx is a Python library that turns a W3C Web of Things Thing Description
into tools an AI agent can call. The description is a JSON document naming a
system's actions and a transport for each; thingctx runs every call over that
transport. No server per integration.

You can add a policy gate that decides each call before any transport runs:
allow reads, deny writes, or ask a human first. The binding holds the
credential; the model never sees it.

## First run

    pip install thingctx

The base install pulls no dependencies. This runs with no keys and no network:

```python
import asyncio

import thingctx
from thingctx.contrib.time import make_time_handler

td = {
    "@context": "https://www.w3.org/2022/wot/td/v1.1",
    "id": "urn:demo:clock",
    "title": "Clock",
    "securityDefinitions": {"nosec_sc": {"scheme": "nosec"}},
    "security": ["nosec_sc"],
    "actions": {
        "getCurrentTime": {
            "input": {
                "type": "object",
                "properties": {"timezone": {"type": "string"}},
            },
            "forms": [{"href": "local://getCurrentTime"}],
        }
    },
}


async def main():
    client = thingctx.ThingClient(
        tds=[td], bindings=[thingctx.LocalBinding(make_time_handler())]
    )
    tools, invoke = client.as_tools()
    print("tools:", [t["function"]["name"] for t in tools])
    print(await invoke("clock__getCurrentTime", {"timezone": "UTC"}))


asyncio.run(main())
```

## Agent loop

Install `'thingctx[llm,http]'`, set your provider key, import thingctx, and
inside an async function:

```python
host = await thingctx.from_url("https://example.com/device.td.json")
print(await host.chat("summarize the device's status"))
```

`from_url` accepts any URL that serves a Thing Description.

Closed agent (Claude Desktop, VS Code)? Install `'thingctx[mcp]'` and bridge a
folder of descriptions:

    thingctx-mcp ./registry/

## Docs and source

Full README, examples, and design notes: https://github.com/thingctx/thingctx

Apache-2.0
