instantly-mcp 0.1.0__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.
- instantly_mcp-0.1.0/.dockerignore +8 -0
- instantly_mcp-0.1.0/.env.example +58 -0
- instantly_mcp-0.1.0/.github/ISSUE_TEMPLATE/bug_report.yml +91 -0
- instantly_mcp-0.1.0/.github/ISSUE_TEMPLATE/config.yml +11 -0
- instantly_mcp-0.1.0/.github/ISSUE_TEMPLATE/feature_request.yml +29 -0
- instantly_mcp-0.1.0/.github/dependabot.yml +32 -0
- instantly_mcp-0.1.0/.github/workflows/ci.yml +53 -0
- instantly_mcp-0.1.0/.github/workflows/release.yml +141 -0
- instantly_mcp-0.1.0/.github/workflows/zizmor.yml +39 -0
- instantly_mcp-0.1.0/.gitignore +21 -0
- instantly_mcp-0.1.0/AGENTS.md +207 -0
- instantly_mcp-0.1.0/CHANGELOG.md +126 -0
- instantly_mcp-0.1.0/CLAUDE.md +1 -0
- instantly_mcp-0.1.0/CODE_OF_CONDUCT.md +136 -0
- instantly_mcp-0.1.0/CONTRIBUTING.md +61 -0
- instantly_mcp-0.1.0/Dockerfile +30 -0
- instantly_mcp-0.1.0/LICENSE +21 -0
- instantly_mcp-0.1.0/PKG-INFO +247 -0
- instantly_mcp-0.1.0/README.md +216 -0
- instantly_mcp-0.1.0/SECURITY.md +53 -0
- instantly_mcp-0.1.0/docs/api-notes.md +52 -0
- instantly_mcp-0.1.0/docs/autonomy.md +82 -0
- instantly_mcp-0.1.0/docs/configuration.md +56 -0
- instantly_mcp-0.1.0/docs/hosting.md +109 -0
- instantly_mcp-0.1.0/docs/tools.md +74 -0
- instantly_mcp-0.1.0/pyproject.toml +104 -0
- instantly_mcp-0.1.0/render.yaml +44 -0
- instantly_mcp-0.1.0/src/instantly_mcp/__init__.py +3 -0
- instantly_mcp-0.1.0/src/instantly_mcp/auth.py +144 -0
- instantly_mcp-0.1.0/src/instantly_mcp/client.py +199 -0
- instantly_mcp-0.1.0/src/instantly_mcp/formatting.py +232 -0
- instantly_mcp-0.1.0/src/instantly_mcp/models.py +171 -0
- instantly_mcp-0.1.0/src/instantly_mcp/oauth.py +356 -0
- instantly_mcp-0.1.0/src/instantly_mcp/policy.py +237 -0
- instantly_mcp-0.1.0/src/instantly_mcp/server.py +964 -0
- instantly_mcp-0.1.0/tests/__init__.py +0 -0
- instantly_mcp-0.1.0/tests/test_auth.py +112 -0
- instantly_mcp-0.1.0/tests/test_client.py +178 -0
- instantly_mcp-0.1.0/tests/test_oauth.py +294 -0
- instantly_mcp-0.1.0/tests/test_policy.py +377 -0
- instantly_mcp-0.1.0/tests/test_server.py +67 -0
- instantly_mcp-0.1.0/tests/test_tools.py +231 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# Copy to .env and fill in. .env is gitignored; never commit real values.
|
|
2
|
+
# Full reference (defaults + behavior) in docs/configuration.md.
|
|
3
|
+
|
|
4
|
+
# --- Required ---------------------------------------------------------------
|
|
5
|
+
# Your Instantly v2 API key (a scoped Bearer token).
|
|
6
|
+
# Generate it in Instantly -> Settings -> Integrations -> API.
|
|
7
|
+
# Tip: start with a READ-ONLY scoped key to try analytics safely, then widen.
|
|
8
|
+
INSTANTLY_API_KEY=
|
|
9
|
+
|
|
10
|
+
# --- Optional: base URL / transport ----------------------------------------
|
|
11
|
+
# Override only if Instantly changes their host. Default shown.
|
|
12
|
+
# INSTANTLY_BASE_URL=https://api.instantly.ai/api/v2
|
|
13
|
+
|
|
14
|
+
# Transport for the MCP server. Default "stdio" (local, launched by the client).
|
|
15
|
+
# Switch to "streamable-http" or "sse" when hosting (see docs/hosting.md).
|
|
16
|
+
# TRANSPORT=stdio
|
|
17
|
+
# HOST=0.0.0.0
|
|
18
|
+
# PORT=8000
|
|
19
|
+
|
|
20
|
+
# --- Required WHEN HOSTED (TRANSPORT != stdio) ------------------------------
|
|
21
|
+
# Over stdio the only caller is a local process, so these are unused. Over HTTP
|
|
22
|
+
# every tool is exposed to anyone who can reach the URL, so the server REFUSES
|
|
23
|
+
# TO START without them. Note AUTONOMY_LEVEL is not a defence here: `confirm`
|
|
24
|
+
# is supplied by the caller, so an anonymous caller just sets it to true.
|
|
25
|
+
#
|
|
26
|
+
# Shared bearer token Claude must present. Min 32 chars. Generate with:
|
|
27
|
+
# python -c "import secrets; print(secrets.token_urlsafe(32))"
|
|
28
|
+
# This value doubles as the passphrase on the /login page during the OAuth
|
|
29
|
+
# connect flow -- there is no separate password. See docs/hosting.md.
|
|
30
|
+
# MCP_AUTH_TOKEN=
|
|
31
|
+
#
|
|
32
|
+
# The public https:// URL Claude connects to. Must be https (a bearer token over
|
|
33
|
+
# plain http is sent in clear text); http://127.0.0.1 is allowed for local tests.
|
|
34
|
+
# PUBLIC_URL=https://your-app.example.com
|
|
35
|
+
#
|
|
36
|
+
# Hosts accepted as OAuth callbacks, comma separated. Only change this if your
|
|
37
|
+
# client redirects from a domain not in the default list -- a rejected
|
|
38
|
+
# registration surfaces as "invalid_redirect_uri" at connect time.
|
|
39
|
+
# OAUTH_REDIRECT_HOSTS=claude.ai,claude.com,anthropic.com
|
|
40
|
+
|
|
41
|
+
# --- Optional: autonomy policy ---------------------------------------------
|
|
42
|
+
# manual (default) | assisted | autonomous -- see docs/autonomy.md.
|
|
43
|
+
# AUTONOMY_LEVEL=manual
|
|
44
|
+
|
|
45
|
+
# Volume caps (enforced in code). Exceeding a cap forces a confirm preview
|
|
46
|
+
# even in autonomous mode.
|
|
47
|
+
# INSTANTLY_MAX_LEADS_PER_CALL=1000
|
|
48
|
+
# INSTANTLY_MAX_LEADS_PER_DAY=5000
|
|
49
|
+
# INSTANTLY_MAX_EMAILS_PER_DAY=50
|
|
50
|
+
# INSTANTLY_MAX_CAMPAIGNS_PER_CALL=1
|
|
51
|
+
|
|
52
|
+
# Optional allow/deny lists (comma-separated campaign UUIDs). If an allowlist
|
|
53
|
+
# is set, autonomous actions may only touch those campaigns.
|
|
54
|
+
# INSTANTLY_CAMPAIGN_ALLOWLIST=
|
|
55
|
+
# INSTANTLY_CAMPAIGN_DENYLIST=
|
|
56
|
+
|
|
57
|
+
# Where to append the audit log of executed writes. Default ./audit.log
|
|
58
|
+
# INSTANTLY_AUDIT_LOG=audit.log
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
name: Bug report
|
|
2
|
+
description: A tool misbehaved, or a safety gate didn't do what the docs say it does.
|
|
3
|
+
labels: ["bug"]
|
|
4
|
+
body:
|
|
5
|
+
- type: markdown
|
|
6
|
+
attributes:
|
|
7
|
+
value: |
|
|
8
|
+
Thanks for reporting. If a write executed **without** `confirm=true`
|
|
9
|
+
and without the autonomy policy explicitly permitting it, or a
|
|
10
|
+
hard-blocked tool (`delete_lead`, `delete_webhook`, `pause_account`,
|
|
11
|
+
`remove_from_blocklist`) ran autonomously, please report that
|
|
12
|
+
[privately as a security
|
|
13
|
+
issue](https://github.com/katekruger/instantly-mcp/security/advisories/new)
|
|
14
|
+
instead — that is the exact failure mode this project exists to
|
|
15
|
+
prevent.
|
|
16
|
+
|
|
17
|
+
- type: input
|
|
18
|
+
id: tool
|
|
19
|
+
attributes:
|
|
20
|
+
label: Tool name
|
|
21
|
+
description: The MCP tool involved, e.g. `add_leads`, `pause_campaign`.
|
|
22
|
+
placeholder: add_leads
|
|
23
|
+
validations:
|
|
24
|
+
required: true
|
|
25
|
+
|
|
26
|
+
- type: textarea
|
|
27
|
+
id: what_happened
|
|
28
|
+
attributes:
|
|
29
|
+
label: What happened
|
|
30
|
+
description: What the tool did or returned.
|
|
31
|
+
validations:
|
|
32
|
+
required: true
|
|
33
|
+
|
|
34
|
+
- type: textarea
|
|
35
|
+
id: expected
|
|
36
|
+
attributes:
|
|
37
|
+
label: What you expected instead
|
|
38
|
+
validations:
|
|
39
|
+
required: true
|
|
40
|
+
|
|
41
|
+
- type: textarea
|
|
42
|
+
id: reproduction
|
|
43
|
+
attributes:
|
|
44
|
+
label: Minimal reproduction
|
|
45
|
+
description: >
|
|
46
|
+
The tool call and arguments that trigger it. **Replace real API keys,
|
|
47
|
+
campaign IDs, and lead emails with placeholders before pasting** —
|
|
48
|
+
`example.com` addresses and `camp-xxxx` style IDs are fine.
|
|
49
|
+
render: json
|
|
50
|
+
validations:
|
|
51
|
+
required: true
|
|
52
|
+
|
|
53
|
+
- type: input
|
|
54
|
+
id: version
|
|
55
|
+
attributes:
|
|
56
|
+
label: Version
|
|
57
|
+
description: Package version (`pip show instantly-mcp`) or commit SHA.
|
|
58
|
+
validations:
|
|
59
|
+
required: true
|
|
60
|
+
|
|
61
|
+
- type: dropdown
|
|
62
|
+
id: transport
|
|
63
|
+
attributes:
|
|
64
|
+
label: Transport
|
|
65
|
+
options:
|
|
66
|
+
- stdio (local)
|
|
67
|
+
- streamable-http (hosted)
|
|
68
|
+
- sse (hosted)
|
|
69
|
+
validations:
|
|
70
|
+
required: true
|
|
71
|
+
|
|
72
|
+
- type: dropdown
|
|
73
|
+
id: autonomy_level
|
|
74
|
+
attributes:
|
|
75
|
+
label: AUTONOMY_LEVEL
|
|
76
|
+
options:
|
|
77
|
+
- manual (default)
|
|
78
|
+
- assisted
|
|
79
|
+
- autonomous
|
|
80
|
+
- not sure
|
|
81
|
+
validations:
|
|
82
|
+
required: true
|
|
83
|
+
|
|
84
|
+
- type: checkboxes
|
|
85
|
+
id: confirmations
|
|
86
|
+
attributes:
|
|
87
|
+
label: Before submitting
|
|
88
|
+
options:
|
|
89
|
+
- label: I have removed any real API keys, tokens, and lead contact data from this report.
|
|
90
|
+
required: true
|
|
91
|
+
- label: I checked docs/autonomy.md to confirm the behavior I'm reporting isn't documented as intended.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Discussions is not enabled on this repo, so "blank" issues stay open for
|
|
2
|
+
# questions and ideas that don't fit the bug/feature forms below, rather than
|
|
3
|
+
# linking to a tab that doesn't exist.
|
|
4
|
+
blank_issues_enabled: true
|
|
5
|
+
contact_links:
|
|
6
|
+
- name: Security vulnerability
|
|
7
|
+
url: https://github.com/katekruger/instantly-mcp/security/advisories/new
|
|
8
|
+
about: >
|
|
9
|
+
Do not open a public issue. A safety gate that let a write through it
|
|
10
|
+
should have blocked — the confirm gate, an autonomy cap, or the
|
|
11
|
+
hard-block list — counts as a security issue; report it here.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
name: Feature request
|
|
2
|
+
description: A new tool, an endpoint not yet covered, or a change to the autonomy policy.
|
|
3
|
+
labels: ["enhancement"]
|
|
4
|
+
body:
|
|
5
|
+
- type: textarea
|
|
6
|
+
id: problem
|
|
7
|
+
attributes:
|
|
8
|
+
label: What are you trying to do
|
|
9
|
+
description: The workflow this would unblock, not just the feature itself.
|
|
10
|
+
validations:
|
|
11
|
+
required: true
|
|
12
|
+
|
|
13
|
+
- type: textarea
|
|
14
|
+
id: proposal
|
|
15
|
+
attributes:
|
|
16
|
+
label: Proposed tool or change
|
|
17
|
+
description: >
|
|
18
|
+
If this is a new tool, what tier should it be (READ / LOW_WRITE /
|
|
19
|
+
HIGH_WRITE) and why? If it's irreversible or high blast radius, should
|
|
20
|
+
it go in HARD_BLOCK? See CONTRIBUTING.md for what a new write tool
|
|
21
|
+
needs to wire up.
|
|
22
|
+
validations:
|
|
23
|
+
required: true
|
|
24
|
+
|
|
25
|
+
- type: textarea
|
|
26
|
+
id: api
|
|
27
|
+
attributes:
|
|
28
|
+
label: Instantly v2 API endpoint(s) involved, if known
|
|
29
|
+
description: Link to https://developer.instantly.ai/ if you have it handy.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
|
|
3
|
+
updates:
|
|
4
|
+
# No lockfile is committed (README supports both uv and venv+pip), so
|
|
5
|
+
# Dependabot reads dependency ranges straight from pyproject.toml.
|
|
6
|
+
- package-ecosystem: "pip"
|
|
7
|
+
directory: "/"
|
|
8
|
+
schedule:
|
|
9
|
+
interval: "weekly"
|
|
10
|
+
day: "monday"
|
|
11
|
+
time: "06:00"
|
|
12
|
+
open-pull-requests-limit: 5
|
|
13
|
+
commit-message:
|
|
14
|
+
prefix: "chore"
|
|
15
|
+
include: "scope"
|
|
16
|
+
labels: ["dependencies"]
|
|
17
|
+
groups:
|
|
18
|
+
dev-tooling:
|
|
19
|
+
patterns: ["pytest*", "ruff"]
|
|
20
|
+
|
|
21
|
+
- package-ecosystem: "github-actions"
|
|
22
|
+
directory: "/"
|
|
23
|
+
schedule:
|
|
24
|
+
interval: "weekly"
|
|
25
|
+
day: "monday"
|
|
26
|
+
time: "06:00"
|
|
27
|
+
commit-message:
|
|
28
|
+
prefix: "ci"
|
|
29
|
+
labels: ["dependencies", "github-actions"]
|
|
30
|
+
groups:
|
|
31
|
+
actions:
|
|
32
|
+
patterns: ["*"]
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
workflow_call:
|
|
8
|
+
workflow_dispatch:
|
|
9
|
+
|
|
10
|
+
permissions:
|
|
11
|
+
contents: read
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
check:
|
|
15
|
+
name: lint, types, tests (py${{ matrix.python-version }})
|
|
16
|
+
runs-on: ubuntu-latest
|
|
17
|
+
strategy:
|
|
18
|
+
fail-fast: false
|
|
19
|
+
matrix:
|
|
20
|
+
python-version: ["3.11", "3.12", "3.13"]
|
|
21
|
+
steps:
|
|
22
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
23
|
+
with:
|
|
24
|
+
persist-credentials: false
|
|
25
|
+
|
|
26
|
+
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
27
|
+
with:
|
|
28
|
+
python-version: ${{ matrix.python-version }}
|
|
29
|
+
cache: pip
|
|
30
|
+
|
|
31
|
+
- name: Install
|
|
32
|
+
run: python -m pip install --upgrade pip && pip install -e ".[dev]"
|
|
33
|
+
|
|
34
|
+
- name: Ruff check
|
|
35
|
+
run: ruff check src tests
|
|
36
|
+
|
|
37
|
+
# ruff format --check is deliberately not run: this codebase predates
|
|
38
|
+
# a formatter pass and has never been through one. Adopting it means
|
|
39
|
+
# reformatting every file in one pass, which is its own reviewed
|
|
40
|
+
# change, not a side effect of adding CI.
|
|
41
|
+
- name: Pyright
|
|
42
|
+
run: pyright
|
|
43
|
+
|
|
44
|
+
# No secrets: the suite is fully mocked and must never reach the live API.
|
|
45
|
+
- name: Test
|
|
46
|
+
run: pytest -q --cov=src/instantly_mcp --cov-report=term-missing
|
|
47
|
+
|
|
48
|
+
# policy.py is the safety module every write-gating claim in the README
|
|
49
|
+
# rests on. Gate it at a real floor so a regression there fails CI
|
|
50
|
+
# specifically, even before the whole-project number earns a threshold
|
|
51
|
+
# (see the comment in pyproject.toml's [tool.coverage.report]).
|
|
52
|
+
- name: Coverage floor for the safety module (policy.py)
|
|
53
|
+
run: coverage report --include='*/instantly_mcp/policy.py' --fail-under=95
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
# Tag-triggered, on the segment-mcp/deliverability-guard pattern: verify the
|
|
4
|
+
# tag matches the package version -> verify CHANGELOG.md has a section for
|
|
5
|
+
# it -> run the full CI suite -> build -> publish to PyPI via Trusted
|
|
6
|
+
# Publishing (OIDC, no API token secret anywhere) into an environment that
|
|
7
|
+
# requires manual approval -> create the GitHub Release from the CHANGELOG
|
|
8
|
+
# section.
|
|
9
|
+
#
|
|
10
|
+
# No MCP Registry job here (segment-mcp has one). This server is deliberately
|
|
11
|
+
# staying local-stdio-only for now -- see docs/hosting.md and CHANGELOG.md --
|
|
12
|
+
# so there is no hosted remote to register, and this repo's own choice has
|
|
13
|
+
# been to not pursue that discoverability yet. PyPI publication is a
|
|
14
|
+
# different, lower-exposure kind of distribution: it ships the same local
|
|
15
|
+
# stdio install the README already documents, just via `pip install
|
|
16
|
+
# instantly-mcp` instead of a git clone, with no public URL, no bearer
|
|
17
|
+
# token, and no secret sitting in a third-party host.
|
|
18
|
+
#
|
|
19
|
+
# Set up the PyPI Trusted Publisher BEFORE pushing the first tag -- PyPI
|
|
20
|
+
# needs to already trust this repo/workflow/environment combination, or the
|
|
21
|
+
# publish step has nothing to authenticate against.
|
|
22
|
+
|
|
23
|
+
on:
|
|
24
|
+
push:
|
|
25
|
+
tags:
|
|
26
|
+
- "v*.*.*"
|
|
27
|
+
|
|
28
|
+
permissions:
|
|
29
|
+
contents: read
|
|
30
|
+
|
|
31
|
+
jobs:
|
|
32
|
+
verify:
|
|
33
|
+
name: verify tag matches version, CHANGELOG has a section
|
|
34
|
+
runs-on: ubuntu-latest
|
|
35
|
+
permissions:
|
|
36
|
+
contents: read
|
|
37
|
+
steps:
|
|
38
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
39
|
+
with:
|
|
40
|
+
persist-credentials: false
|
|
41
|
+
|
|
42
|
+
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
43
|
+
with:
|
|
44
|
+
python-version: "3.12"
|
|
45
|
+
|
|
46
|
+
- run: python -m pip install --upgrade pip hatch
|
|
47
|
+
|
|
48
|
+
- name: Verify tag matches package version
|
|
49
|
+
run: |
|
|
50
|
+
tag_version="${GITHUB_REF_NAME#v}"
|
|
51
|
+
pkg_version="$(hatch version)"
|
|
52
|
+
if [ "$tag_version" != "$pkg_version" ]; then
|
|
53
|
+
echo "::error::tag $GITHUB_REF_NAME (version $tag_version) does not match" \
|
|
54
|
+
"package version $pkg_version (src/instantly_mcp/__init__.py)"
|
|
55
|
+
exit 1
|
|
56
|
+
fi
|
|
57
|
+
echo "OK: tag $GITHUB_REF_NAME matches package version $pkg_version"
|
|
58
|
+
|
|
59
|
+
- name: Verify CHANGELOG.md has a section for this version
|
|
60
|
+
run: |
|
|
61
|
+
pkg_version="$(hatch version)"
|
|
62
|
+
if ! grep -qE "^## \[?${pkg_version//./\\.}\]?" CHANGELOG.md; then
|
|
63
|
+
echo "::error::CHANGELOG.md has no '## $pkg_version' section"
|
|
64
|
+
exit 1
|
|
65
|
+
fi
|
|
66
|
+
echo "OK: CHANGELOG.md has a section for $pkg_version"
|
|
67
|
+
|
|
68
|
+
ci:
|
|
69
|
+
name: run CI
|
|
70
|
+
needs: verify
|
|
71
|
+
uses: $/.github/workflows/ci.yml
|
|
72
|
+
|
|
73
|
+
build:
|
|
74
|
+
name: build sdist and wheel
|
|
75
|
+
needs: ci
|
|
76
|
+
runs-on: ubuntu-latest
|
|
77
|
+
permissions:
|
|
78
|
+
contents: read
|
|
79
|
+
steps:
|
|
80
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
81
|
+
with:
|
|
82
|
+
persist-credentials: false
|
|
83
|
+
|
|
84
|
+
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
85
|
+
with:
|
|
86
|
+
python-version: "3.12"
|
|
87
|
+
|
|
88
|
+
- name: Build
|
|
89
|
+
run: python -m pip install --upgrade pip build && python -m build
|
|
90
|
+
|
|
91
|
+
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
92
|
+
with:
|
|
93
|
+
name: dist
|
|
94
|
+
path: dist/
|
|
95
|
+
|
|
96
|
+
publish:
|
|
97
|
+
name: publish to PyPI
|
|
98
|
+
needs: build
|
|
99
|
+
runs-on: ubuntu-latest
|
|
100
|
+
environment:
|
|
101
|
+
name: release
|
|
102
|
+
url: https://pypi.org/project/instantly-mcp/
|
|
103
|
+
permissions:
|
|
104
|
+
id-token: write # required for PyPI Trusted Publishing (OIDC); no API token anywhere
|
|
105
|
+
contents: read
|
|
106
|
+
steps:
|
|
107
|
+
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
|
108
|
+
with:
|
|
109
|
+
name: dist
|
|
110
|
+
path: dist/
|
|
111
|
+
|
|
112
|
+
# PEP 740 attestations are generated and uploaded automatically here
|
|
113
|
+
# under Trusted Publishing -- no extra configuration -- and show up
|
|
114
|
+
# as a provenance badge on the PyPI project page.
|
|
115
|
+
- name: Publish to PyPI
|
|
116
|
+
uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # v1.14.2
|
|
117
|
+
|
|
118
|
+
github-release:
|
|
119
|
+
name: create GitHub Release
|
|
120
|
+
needs: publish
|
|
121
|
+
runs-on: ubuntu-latest
|
|
122
|
+
permissions:
|
|
123
|
+
contents: write
|
|
124
|
+
steps:
|
|
125
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
126
|
+
with:
|
|
127
|
+
persist-credentials: false
|
|
128
|
+
|
|
129
|
+
- name: Extract this version's CHANGELOG section
|
|
130
|
+
run: |
|
|
131
|
+
pkg_version="$(sed -n 's/^__version__ = "\(.*\)"/\1/p' src/instantly_mcp/__init__.py)"
|
|
132
|
+
awk -v ver="$pkg_version" '
|
|
133
|
+
$0 ~ "^## \\[?" ver { found=1; next }
|
|
134
|
+
found && /^## / { exit }
|
|
135
|
+
found { print }
|
|
136
|
+
' CHANGELOG.md > release-notes.md
|
|
137
|
+
|
|
138
|
+
- name: Create GitHub Release
|
|
139
|
+
env:
|
|
140
|
+
GH_TOKEN: ${{ github.token }}
|
|
141
|
+
run: gh release create "$GITHUB_REF_NAME" --title "$GITHUB_REF_NAME" --notes-file release-notes.md
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
name: zizmor
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: ["**"]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
zizmor:
|
|
11
|
+
name: zizmor GitHub Actions security audit
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
permissions:
|
|
14
|
+
contents: read
|
|
15
|
+
security-events: write
|
|
16
|
+
actions: read
|
|
17
|
+
steps:
|
|
18
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
19
|
+
with:
|
|
20
|
+
persist-credentials: false
|
|
21
|
+
|
|
22
|
+
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
23
|
+
with:
|
|
24
|
+
python-version: "3.12"
|
|
25
|
+
|
|
26
|
+
- name: Run zizmor
|
|
27
|
+
run: pipx run zizmor --format sarif . > results.sarif
|
|
28
|
+
env:
|
|
29
|
+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
30
|
+
|
|
31
|
+
- name: Upload SARIF file
|
|
32
|
+
# Code scanning confirmed enabled: run 33411592691 (2026-08-31)
|
|
33
|
+
# uploaded successfully on the first real push, so this no longer
|
|
34
|
+
# needs the continue-on-error segment-mcp's zizmor.yml carried
|
|
35
|
+
# through its own private-to-public transition.
|
|
36
|
+
uses: github/codeql-action/upload-sarif@cdf488f595d80d6e07e03d4674febd5ab45fa938 # v4.37.9
|
|
37
|
+
with:
|
|
38
|
+
sarif_file: results.sarif
|
|
39
|
+
category: zizmor
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Secrets & audit trail (audit.log may contain lead emails)
|
|
2
|
+
.env
|
|
3
|
+
audit.log
|
|
4
|
+
|
|
5
|
+
# Python
|
|
6
|
+
__pycache__/
|
|
7
|
+
*.py[cod]
|
|
8
|
+
*.egg-info/
|
|
9
|
+
.eggs/
|
|
10
|
+
build/
|
|
11
|
+
dist/
|
|
12
|
+
.venv/
|
|
13
|
+
venv/
|
|
14
|
+
.pytest_cache/
|
|
15
|
+
.mypy_cache/
|
|
16
|
+
.ruff_cache/
|
|
17
|
+
.coverage
|
|
18
|
+
.coverage.*
|
|
19
|
+
htmlcov/
|
|
20
|
+
coverage.xml
|
|
21
|
+
deploy-token.txt
|