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.
Files changed (42) hide show
  1. instantly_mcp-0.1.0/.dockerignore +8 -0
  2. instantly_mcp-0.1.0/.env.example +58 -0
  3. instantly_mcp-0.1.0/.github/ISSUE_TEMPLATE/bug_report.yml +91 -0
  4. instantly_mcp-0.1.0/.github/ISSUE_TEMPLATE/config.yml +11 -0
  5. instantly_mcp-0.1.0/.github/ISSUE_TEMPLATE/feature_request.yml +29 -0
  6. instantly_mcp-0.1.0/.github/dependabot.yml +32 -0
  7. instantly_mcp-0.1.0/.github/workflows/ci.yml +53 -0
  8. instantly_mcp-0.1.0/.github/workflows/release.yml +141 -0
  9. instantly_mcp-0.1.0/.github/workflows/zizmor.yml +39 -0
  10. instantly_mcp-0.1.0/.gitignore +21 -0
  11. instantly_mcp-0.1.0/AGENTS.md +207 -0
  12. instantly_mcp-0.1.0/CHANGELOG.md +126 -0
  13. instantly_mcp-0.1.0/CLAUDE.md +1 -0
  14. instantly_mcp-0.1.0/CODE_OF_CONDUCT.md +136 -0
  15. instantly_mcp-0.1.0/CONTRIBUTING.md +61 -0
  16. instantly_mcp-0.1.0/Dockerfile +30 -0
  17. instantly_mcp-0.1.0/LICENSE +21 -0
  18. instantly_mcp-0.1.0/PKG-INFO +247 -0
  19. instantly_mcp-0.1.0/README.md +216 -0
  20. instantly_mcp-0.1.0/SECURITY.md +53 -0
  21. instantly_mcp-0.1.0/docs/api-notes.md +52 -0
  22. instantly_mcp-0.1.0/docs/autonomy.md +82 -0
  23. instantly_mcp-0.1.0/docs/configuration.md +56 -0
  24. instantly_mcp-0.1.0/docs/hosting.md +109 -0
  25. instantly_mcp-0.1.0/docs/tools.md +74 -0
  26. instantly_mcp-0.1.0/pyproject.toml +104 -0
  27. instantly_mcp-0.1.0/render.yaml +44 -0
  28. instantly_mcp-0.1.0/src/instantly_mcp/__init__.py +3 -0
  29. instantly_mcp-0.1.0/src/instantly_mcp/auth.py +144 -0
  30. instantly_mcp-0.1.0/src/instantly_mcp/client.py +199 -0
  31. instantly_mcp-0.1.0/src/instantly_mcp/formatting.py +232 -0
  32. instantly_mcp-0.1.0/src/instantly_mcp/models.py +171 -0
  33. instantly_mcp-0.1.0/src/instantly_mcp/oauth.py +356 -0
  34. instantly_mcp-0.1.0/src/instantly_mcp/policy.py +237 -0
  35. instantly_mcp-0.1.0/src/instantly_mcp/server.py +964 -0
  36. instantly_mcp-0.1.0/tests/__init__.py +0 -0
  37. instantly_mcp-0.1.0/tests/test_auth.py +112 -0
  38. instantly_mcp-0.1.0/tests/test_client.py +178 -0
  39. instantly_mcp-0.1.0/tests/test_oauth.py +294 -0
  40. instantly_mcp-0.1.0/tests/test_policy.py +377 -0
  41. instantly_mcp-0.1.0/tests/test_server.py +67 -0
  42. instantly_mcp-0.1.0/tests/test_tools.py +231 -0
@@ -0,0 +1,8 @@
1
+ .venv/
2
+ .git/
3
+ .pytest_cache/
4
+ __pycache__/
5
+ *.pyc
6
+ .env
7
+ audit.log
8
+ tests/
@@ -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