ivcap-lambda 0.7.25__tar.gz → 0.8.1__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.
@@ -0,0 +1,200 @@
1
+ Metadata-Version: 2.4
2
+ Name: ivcap-lambda
3
+ Version: 0.8.1
4
+ Summary: Helper functions for building lambda-style services on the IVCAP platform
5
+ License-File: AUTHORS.md
6
+ License-File: LICENSE
7
+ Author: Max Ott
8
+ Author-email: max.ott@csiro.au
9
+ Requires-Python: >=3.11,<4.0
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3.11
12
+ Classifier: Programming Language :: Python :: 3.12
13
+ Classifier: Programming Language :: Python :: 3.13
14
+ Classifier: Programming Language :: Python :: 3.14
15
+ Provides-Extra: mcp
16
+ Requires-Dist: cachetools (>=5.5.2,<6.0.0)
17
+ Requires-Dist: fastapi (>=0.121.2,<0.122.0)
18
+ Requires-Dist: ivcap-service (>=0.7.0,<0.8.0)
19
+ Requires-Dist: mcp (>=2.3.0,<3.0.0) ; extra == "mcp"
20
+ Requires-Dist: opentelemetry-instrumentation-fastapi (>=0.57b0)
21
+ Requires-Dist: uuid6 (==2024.7.10)
22
+ Requires-Dist: uvicorn (>=0.38.0,<0.39.0)
23
+ Description-Content-Type: text/markdown
24
+
25
+ # ivcap-lambda: Python SDK for Lambda-Style IVCAP Services
26
+
27
+ > **Package renamed:** `ivcap-ai-tool` has been renamed to `ivcap-lambda` to reflect that
28
+ > the library is useful for any lambda-style IVCAP service, not just AI agent tools.
29
+ > A [compatibility shim](./compat/) is published under the old name — existing apps
30
+ > will continue to work but will see a `DeprecationWarning` prompting migration.
31
+
32
+ <a href="https://scan.coverity.com/projects/ivcap-works-ivcap-ai-tool-sdk-python">
33
+ <img alt="Coverity Scan Build Status"
34
+ src="https://img.shields.io/coverity/scan/31491.svg"/>
35
+ </a>
36
+
37
+ `ivcap-lambda` is a Python library that turns a plain Python function into a set of
38
+ **IVCAP-compatible HTTP endpoints** and/or a **spec-compliant MCP (Model Context
39
+ Protocol) server**, from the same tool code. It sits on top of
40
+ [`ivcap-service`](https://pypi.org/project/ivcap-service/) and
41
+ [FastAPI](https://fastapi.tiangolo.com/), and handles:
42
+
43
+ - Registering tool functions as HTTP endpoints (with async "try-later" semantics)
44
+ - Job execution in threads, result caching, and graceful shutdown
45
+ - Event/progress reporting back to the IVCAP platform
46
+ - Automatic tool-description endpoints (for AI agents) and an optional MCP endpoint
47
+ (built on the official [`mcp`](https://pypi.org/project/mcp/) Python SDK)
48
+
49
+ **📖 Full documentation:** <https://ivcap-works.github.io/ivcap-ai-tool-sdk-python/>
50
+
51
+ **🚀 New to the library?** Depending on your goal:
52
+
53
+ - Building a service for the **IVCAP platform** (MCP optional) → see
54
+ [AGENTS.md, Track A](./AGENTS.md#track-a-ivcap-lambda-service) or the
55
+ [Quick Start guide](https://ivcap-works.github.io/ivcap-ai-tool-sdk-python/getting-started/quick-start/)
56
+ - Building an **MCP server** first, with IVCAP deployment as a bonus → see
57
+ [AGENTS.md, Track B](./AGENTS.md#track-b-mcp-first-server) or the
58
+ [MCP guide's MCP-first section](https://ivcap-works.github.io/ivcap-ai-tool-sdk-python/guides/mcp/#mcp-first-development)
59
+ - A ready-to-clone starter project →
60
+ [ivcap-python-ai-tool-template](https://github.com/ivcap-works/ivcap-python-ai-tool-template)
61
+
62
+ ---
63
+
64
+ ## Installation
65
+
66
+ ```bash
67
+ pip install ivcap-lambda
68
+
69
+ # To also expose tools as an MCP server:
70
+ pip install ivcap-lambda[mcp]
71
+ ```
72
+
73
+ ## Minimal Example
74
+
75
+ ```python
76
+ from pydantic import BaseModel, Field
77
+ from ivcap_service import Service, getLogger, with_schema
78
+ from ivcap_lambda import start_lambda_server, ivcap_lambda, ToolOptions, logging_init
79
+
80
+ logging_init()
81
+ logger = getLogger("my-service")
82
+
83
+ service = Service(
84
+ name="My IVCAP Service",
85
+ description="A minimal example service.",
86
+ contact={"name": "Alice", "email": "alice@example.com"},
87
+ license={"name": "MIT", "url": "https://opensource.org/licenses/MIT"},
88
+ )
89
+
90
+
91
+ @with_schema("urn:example:schema:echo.request.1")
92
+ class EchoRequest(BaseModel):
93
+ message: str = Field(..., description="The message to echo back.")
94
+
95
+
96
+ @with_schema("urn:example:schema:echo.1")
97
+ class EchoResult(BaseModel):
98
+ echo: str = Field(..., description="The echoed message.")
99
+
100
+
101
+ @ivcap_lambda("/", opts=ToolOptions(tags=["Echo"]))
102
+ def echo(req: EchoRequest) -> EchoResult:
103
+ """Echo a message
104
+
105
+ Returns the message passed in the request unchanged.
106
+ """
107
+ return EchoResult(echo=req.message)
108
+
109
+
110
+ if __name__ == "__main__":
111
+ start_lambda_server(service)
112
+ ```
113
+
114
+ Run and test it:
115
+
116
+ ```bash
117
+ python my_service.py --port 8090
118
+ curl -X POST http://localhost:8090/ -H "content-type: application/json" -d '{"message": "Hello, IVCAP!"}'
119
+
120
+ # Or, with the mcp extra installed, run the exact same tool as an MCP server instead:
121
+ python my_service.py --with-mcp-stdio
122
+ ```
123
+
124
+ For everything else — defining tools, `ToolOptions`, `JobContext`, progress
125
+ reporting, artifacts, MCP, project layout, deployment, Docker — see the
126
+ **[full documentation](https://ivcap-works.github.io/ivcap-ai-tool-sdk-python/)**
127
+ and **[AGENTS.md](./AGENTS.md)**. This README intentionally stays limited to
128
+ installation/quick-start plus notes for anyone working on `ivcap-lambda`
129
+ itself (below), to avoid duplicating content that's already maintained in the
130
+ docs site.
131
+
132
+ ---
133
+
134
+ ## Migration from `ivcap-ai-tool`
135
+
136
+ | Old (deprecated) | New |
137
+ |---|---|
138
+ | `pip install ivcap-ai-tool` | `pip install ivcap-lambda` |
139
+ | `from ivcap_ai_tool import ...` | `from ivcap_lambda import ...` |
140
+ | `@ivcap_ai_tool(...)` | `@ivcap_lambda(...)` |
141
+
142
+ The old `ivcap-ai-tool` package is a compatibility shim that re-exports everything from `ivcap-lambda`. It will emit a `DeprecationWarning` at import time. No code changes beyond the import are required.
143
+
144
+ ---
145
+
146
+ ## Contributing / Developing `ivcap-lambda` Itself
147
+
148
+ The sections below are for anyone extending, fixing, or releasing this
149
+ library — not for consumers of the package. See also
150
+ [CONTRIBUTING.md](./CONTRIBUTING.md), [DESIGN.md](./DESIGN.md) (internal
151
+ architecture), and [CONDUCT.md](./CONDUCT.md).
152
+
153
+ ### Repository Layout
154
+
155
+ ```
156
+ ivcap-ai-tool/
157
+ ├── ivcap_lambda/ # the library itself
158
+ ├── compat/ # ivcap-ai-tool deprecation shim (old package name)
159
+ ├── docs/ # MkDocs documentation site (docs/docs) + build output (docs/site)
160
+ ├── examples/ # runnable example services (test-tool, test-mcp)
161
+ ├── tests/ # unit tests
162
+ ├── AGENTS.md # user-facing reference for AI coding agents
163
+ ├── DESIGN.md # internal architecture & design rationale
164
+ └── pyproject.toml
165
+ ```
166
+
167
+ ### Setup, Tests & Checks
168
+
169
+ ```bash
170
+ poetry install
171
+ make test # pytest --cov=ivcap_lambda
172
+ make check # test + ruff check + mypy
173
+ ```
174
+
175
+ ### Running the Example Services
176
+
177
+ ```bash
178
+ cd examples/test-tool && poetry install && make run # REST example
179
+ cd examples/test-mcp && poetry install && make run # MCP example (HTTP)
180
+ cd examples/test-mcp && make run-mcp-stdio # MCP example (stdio)
181
+ ```
182
+
183
+ ### Building & Serving the Documentation Site
184
+
185
+ ```bash
186
+ make docs-serve # live-reload at a random local port
187
+ make docs-build # build static site into docs/site
188
+ ```
189
+
190
+ ### Releasing
191
+
192
+ Versioning/publishing is driven by `semantic_release` config in
193
+ `pyproject.toml` on `main`. `make build` / `make publish` wrap `poetry
194
+ build`/`poetry publish`.
195
+
196
+ ### License
197
+
198
+ Licensed under the BSD-style license in [LICENSE](./LICENSE). See
199
+ [AUTHORS.md](./AUTHORS.md) for contributors.
200
+
@@ -0,0 +1,175 @@
1
+ # ivcap-lambda: Python SDK for Lambda-Style IVCAP Services
2
+
3
+ > **Package renamed:** `ivcap-ai-tool` has been renamed to `ivcap-lambda` to reflect that
4
+ > the library is useful for any lambda-style IVCAP service, not just AI agent tools.
5
+ > A [compatibility shim](./compat/) is published under the old name — existing apps
6
+ > will continue to work but will see a `DeprecationWarning` prompting migration.
7
+
8
+ <a href="https://scan.coverity.com/projects/ivcap-works-ivcap-ai-tool-sdk-python">
9
+ <img alt="Coverity Scan Build Status"
10
+ src="https://img.shields.io/coverity/scan/31491.svg"/>
11
+ </a>
12
+
13
+ `ivcap-lambda` is a Python library that turns a plain Python function into a set of
14
+ **IVCAP-compatible HTTP endpoints** and/or a **spec-compliant MCP (Model Context
15
+ Protocol) server**, from the same tool code. It sits on top of
16
+ [`ivcap-service`](https://pypi.org/project/ivcap-service/) and
17
+ [FastAPI](https://fastapi.tiangolo.com/), and handles:
18
+
19
+ - Registering tool functions as HTTP endpoints (with async "try-later" semantics)
20
+ - Job execution in threads, result caching, and graceful shutdown
21
+ - Event/progress reporting back to the IVCAP platform
22
+ - Automatic tool-description endpoints (for AI agents) and an optional MCP endpoint
23
+ (built on the official [`mcp`](https://pypi.org/project/mcp/) Python SDK)
24
+
25
+ **📖 Full documentation:** <https://ivcap-works.github.io/ivcap-ai-tool-sdk-python/>
26
+
27
+ **🚀 New to the library?** Depending on your goal:
28
+
29
+ - Building a service for the **IVCAP platform** (MCP optional) → see
30
+ [AGENTS.md, Track A](./AGENTS.md#track-a-ivcap-lambda-service) or the
31
+ [Quick Start guide](https://ivcap-works.github.io/ivcap-ai-tool-sdk-python/getting-started/quick-start/)
32
+ - Building an **MCP server** first, with IVCAP deployment as a bonus → see
33
+ [AGENTS.md, Track B](./AGENTS.md#track-b-mcp-first-server) or the
34
+ [MCP guide's MCP-first section](https://ivcap-works.github.io/ivcap-ai-tool-sdk-python/guides/mcp/#mcp-first-development)
35
+ - A ready-to-clone starter project →
36
+ [ivcap-python-ai-tool-template](https://github.com/ivcap-works/ivcap-python-ai-tool-template)
37
+
38
+ ---
39
+
40
+ ## Installation
41
+
42
+ ```bash
43
+ pip install ivcap-lambda
44
+
45
+ # To also expose tools as an MCP server:
46
+ pip install ivcap-lambda[mcp]
47
+ ```
48
+
49
+ ## Minimal Example
50
+
51
+ ```python
52
+ from pydantic import BaseModel, Field
53
+ from ivcap_service import Service, getLogger, with_schema
54
+ from ivcap_lambda import start_lambda_server, ivcap_lambda, ToolOptions, logging_init
55
+
56
+ logging_init()
57
+ logger = getLogger("my-service")
58
+
59
+ service = Service(
60
+ name="My IVCAP Service",
61
+ description="A minimal example service.",
62
+ contact={"name": "Alice", "email": "alice@example.com"},
63
+ license={"name": "MIT", "url": "https://opensource.org/licenses/MIT"},
64
+ )
65
+
66
+
67
+ @with_schema("urn:example:schema:echo.request.1")
68
+ class EchoRequest(BaseModel):
69
+ message: str = Field(..., description="The message to echo back.")
70
+
71
+
72
+ @with_schema("urn:example:schema:echo.1")
73
+ class EchoResult(BaseModel):
74
+ echo: str = Field(..., description="The echoed message.")
75
+
76
+
77
+ @ivcap_lambda("/", opts=ToolOptions(tags=["Echo"]))
78
+ def echo(req: EchoRequest) -> EchoResult:
79
+ """Echo a message
80
+
81
+ Returns the message passed in the request unchanged.
82
+ """
83
+ return EchoResult(echo=req.message)
84
+
85
+
86
+ if __name__ == "__main__":
87
+ start_lambda_server(service)
88
+ ```
89
+
90
+ Run and test it:
91
+
92
+ ```bash
93
+ python my_service.py --port 8090
94
+ curl -X POST http://localhost:8090/ -H "content-type: application/json" -d '{"message": "Hello, IVCAP!"}'
95
+
96
+ # Or, with the mcp extra installed, run the exact same tool as an MCP server instead:
97
+ python my_service.py --with-mcp-stdio
98
+ ```
99
+
100
+ For everything else — defining tools, `ToolOptions`, `JobContext`, progress
101
+ reporting, artifacts, MCP, project layout, deployment, Docker — see the
102
+ **[full documentation](https://ivcap-works.github.io/ivcap-ai-tool-sdk-python/)**
103
+ and **[AGENTS.md](./AGENTS.md)**. This README intentionally stays limited to
104
+ installation/quick-start plus notes for anyone working on `ivcap-lambda`
105
+ itself (below), to avoid duplicating content that's already maintained in the
106
+ docs site.
107
+
108
+ ---
109
+
110
+ ## Migration from `ivcap-ai-tool`
111
+
112
+ | Old (deprecated) | New |
113
+ |---|---|
114
+ | `pip install ivcap-ai-tool` | `pip install ivcap-lambda` |
115
+ | `from ivcap_ai_tool import ...` | `from ivcap_lambda import ...` |
116
+ | `@ivcap_ai_tool(...)` | `@ivcap_lambda(...)` |
117
+
118
+ The old `ivcap-ai-tool` package is a compatibility shim that re-exports everything from `ivcap-lambda`. It will emit a `DeprecationWarning` at import time. No code changes beyond the import are required.
119
+
120
+ ---
121
+
122
+ ## Contributing / Developing `ivcap-lambda` Itself
123
+
124
+ The sections below are for anyone extending, fixing, or releasing this
125
+ library — not for consumers of the package. See also
126
+ [CONTRIBUTING.md](./CONTRIBUTING.md), [DESIGN.md](./DESIGN.md) (internal
127
+ architecture), and [CONDUCT.md](./CONDUCT.md).
128
+
129
+ ### Repository Layout
130
+
131
+ ```
132
+ ivcap-ai-tool/
133
+ ├── ivcap_lambda/ # the library itself
134
+ ├── compat/ # ivcap-ai-tool deprecation shim (old package name)
135
+ ├── docs/ # MkDocs documentation site (docs/docs) + build output (docs/site)
136
+ ├── examples/ # runnable example services (test-tool, test-mcp)
137
+ ├── tests/ # unit tests
138
+ ├── AGENTS.md # user-facing reference for AI coding agents
139
+ ├── DESIGN.md # internal architecture & design rationale
140
+ └── pyproject.toml
141
+ ```
142
+
143
+ ### Setup, Tests & Checks
144
+
145
+ ```bash
146
+ poetry install
147
+ make test # pytest --cov=ivcap_lambda
148
+ make check # test + ruff check + mypy
149
+ ```
150
+
151
+ ### Running the Example Services
152
+
153
+ ```bash
154
+ cd examples/test-tool && poetry install && make run # REST example
155
+ cd examples/test-mcp && poetry install && make run # MCP example (HTTP)
156
+ cd examples/test-mcp && make run-mcp-stdio # MCP example (stdio)
157
+ ```
158
+
159
+ ### Building & Serving the Documentation Site
160
+
161
+ ```bash
162
+ make docs-serve # live-reload at a random local port
163
+ make docs-build # build static site into docs/site
164
+ ```
165
+
166
+ ### Releasing
167
+
168
+ Versioning/publishing is driven by `semantic_release` config in
169
+ `pyproject.toml` on `main`. `make build` / `make publish` wrap `poetry
170
+ build`/`poetry publish`.
171
+
172
+ ### License
173
+
174
+ Licensed under the BSD-style license in [LICENSE](./LICENSE). See
175
+ [AUTHORS.md](./AUTHORS.md) for contributors.
@@ -155,7 +155,12 @@ class Executor(Generic[T]):
155
155
  raise Exception(f"unexpected function parameter '{k}'")
156
156
 
157
157
  async def execute(
158
- self, param: Any, job_id: str, req: Request, report_result=True
158
+ self,
159
+ param: Any,
160
+ job_id: str,
161
+ req: Request,
162
+ report_result=True,
163
+ reporter: EventReporter | None = None,
159
164
  ) -> asyncio.Queue[T | ExecutionError]:
160
165
  """
161
166
  Execute the function with the given parameter in a thread and return a queue with the result.
@@ -163,7 +168,13 @@ class Executor(Generic[T]):
163
168
  Args:
164
169
  param: Any The parameter to pass to the function
165
170
  job_id: str ID of this job
166
- req: Request FastAPI's request object
171
+ req: Request FastAPI's request object (or any duck-typed object
172
+ exposing a `.headers.get(...)` mapping, e.g. an MCP request shim)
173
+ report_result: whether to push the result back to the IVCAP sidecar
174
+ reporter: optional `EventReporter` instance to use for this invocation
175
+ instead of the one produced by the globally configured event-reporter
176
+ factory (e.g. `SidecarReporter`). Used to bridge progress reporting to
177
+ non-REST transports such as MCP.
167
178
 
168
179
  Returns:
169
180
  An asyncio Queue that will contain either the result of type T or an ExecutionError
@@ -200,7 +211,9 @@ class Executor(Generic[T]):
200
211
  jctxt = JobContext(
201
212
  job_id=job_id,
202
213
  job_authorization=authorization,
203
- report=create_event_reporter(
214
+ report=reporter
215
+ if reporter is not None
216
+ else create_event_reporter(
204
217
  job_id=job_id, job_authorization=authorization
205
218
  ),
206
219
  )