Metadata-Version: 2.4
Name: gatecore-langchain
Version: 0.1.4
Summary: LangChain tools for GateCore marketplace discovery, procurement, and governed execution
Author-email: GateCore AI LLC <hello@gatecoreai.com>
License-Expression: Apache-2.0
Project-URL: Homepage, https://gatecoreai.com
Project-URL: Repository, https://github.com/GateCoreAI-com/gatecore-mcp
Classifier: Development Status :: 4 - Beta
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
License-File: NOTICE
Requires-Dist: gatecore-sdk<0.2.0,>=0.1.0
Requires-Dist: httpx<0.29.0,>=0.27.2
Requires-Dist: langchain-core<2.0.0,>=1.0.0
Requires-Dist: mcp==1.28.1
Dynamic: license-file

# gatecore-langchain

`gatecore-langchain` provides three LangChain tools for GateCore marketplace discovery and
procurement, plus helpers that execute a procured capability through GateCore's signed gateway.
The adapter contains transport and configuration only; GateCore services enforce identity,
policy, trust, pricing, funding, delegation, and settlement.

The MCP tools support public `full`-mode GateCore endpoints only. `read` mode passes the server's
fail-closed procurement error through unchanged. `off` mode is unsupported because it does not
replace the adapter's legacy placeholder identity with the MCP credential identity.

## Install from the GateCore monorepo

```bash
python -m pip install -e ./libs/sdk -e ./libs/adapters/gatecore-langchain
```

## Install from PyPI

```bash
python -m pip install gatecore-langchain
```

Read the [ten-minute public guide](https://gatecoreai.com/quickstart/).

## Configuration

Discovery is keyless. `discover_listings` and `get_listing` are public reads on the GateCore MCP
endpoint: they need no key and no account, only the endpoint URL:

```text
GATECORE_MCP_URL=https://mcp.gatecoreai.com/mcp
```

Procurement needs a GateCore MCP access key (`gcmk_...`). `procure`, `list_procurements`, and
`submit_lead` are rejected without one, because agent identity and tenant scope come from the
credential. This adapter's `gatecore_procure` tool is the one that needs it:

```text
GATECORE_MCP_KEY=gcmk_...
```

A key that is set but malformed fails at toolkit construction; a key that is absent is only an
error when a tool that needs one is called.

`execute_procured` and `aexecute_procured` validate these variables lazily on first use:

```text
GATECORE_GATEWAY_URL=https://api.gatecoreai.com
GATECORE_BEARER_TOKEN=...
GATECORE_AGENT_ID=agent:example
GATECORE_ACCESS_GRANT_ID=grant:example
GATECORE_KEY_ID=key:example
GATECORE_PRIVATE_KEY_PATH=/secure/path/agent-key.pem
```

Set exactly one of `GATECORE_PRIVATE_KEY_PATH` or `GATECORE_PRIVATE_KEY_PEM`.

## Quick start

Discovery is copy-paste complete and needs no key:

```python
import os

os.environ["GATECORE_MCP_URL"] = "https://mcp.gatecoreai.com/mcp"

from gatecore_langchain import GateCoreToolkit

tools = GateCoreToolkit().get_tools()
for tool in tools:
    print(tool.name, "-", tool.description.splitlines()[0])

listings = tools[0].invoke({"query": "data"})  # keyless
print(listings[0]["listing_id"])
```

Procurement is the step that needs a key. A free Developer key (1,000 governed transactions a
month, no card) is minted at
[app.gatecoreai.com/developer/portal](https://app.gatecoreai.com/developer/portal); set it as
`GATECORE_MCP_KEY` before calling `gatecore_procure`.

Procurement runs over `GATECORE_MCP_URL` and `GATECORE_MCP_KEY` alone. Executing a procured
capability through the signed gateway uses `execute_procured` and the gateway variables above:

```python
from gatecore_langchain import GateCoreToolkit, execute_procured

tools = GateCoreToolkit().get_tools()
procure_result = tools[2].invoke({"listing_id": "listing:example"})
decision = execute_procured(procure_result, {"query": "example"})
```

All tools are async-native through LangChain's async invocation methods. Their synchronous bridge
uses `asyncio.run()` and therefore must not be called from a thread that already owns a running
event loop; use `ainvoke()` in async applications.
