keycloak-mcp-server 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 (74) hide show
  1. keycloak_mcp_server-0.1.0/.containerignore +43 -0
  2. keycloak_mcp_server-0.1.0/.devcontainer/devcontainer.json +33 -0
  3. keycloak_mcp_server-0.1.0/.env.example +35 -0
  4. keycloak_mcp_server-0.1.0/.github/ISSUE_TEMPLATE/bug_report.yml +101 -0
  5. keycloak_mcp_server-0.1.0/.github/ISSUE_TEMPLATE/config.yml +8 -0
  6. keycloak_mcp_server-0.1.0/.github/ISSUE_TEMPLATE/feature_request.yml +79 -0
  7. keycloak_mcp_server-0.1.0/.github/PULL_REQUEST_TEMPLATE.md +36 -0
  8. keycloak_mcp_server-0.1.0/.github/dependabot.yml +32 -0
  9. keycloak_mcp_server-0.1.0/.github/workflows/pre-commit.yml +35 -0
  10. keycloak_mcp_server-0.1.0/.github/workflows/publish-pypi.yml +89 -0
  11. keycloak_mcp_server-0.1.0/.github/workflows/stale.yml +46 -0
  12. keycloak_mcp_server-0.1.0/.github/workflows/test.yml +47 -0
  13. keycloak_mcp_server-0.1.0/.gitignore +71 -0
  14. keycloak_mcp_server-0.1.0/.pre-commit-config.yaml +47 -0
  15. keycloak_mcp_server-0.1.0/.python-version +1 -0
  16. keycloak_mcp_server-0.1.0/CHANGELOG.md +21 -0
  17. keycloak_mcp_server-0.1.0/CONTRIBUTING.md +253 -0
  18. keycloak_mcp_server-0.1.0/Containerfile +24 -0
  19. keycloak_mcp_server-0.1.0/LICENSE +201 -0
  20. keycloak_mcp_server-0.1.0/Makefile +105 -0
  21. keycloak_mcp_server-0.1.0/PKG-INFO +294 -0
  22. keycloak_mcp_server-0.1.0/README.md +262 -0
  23. keycloak_mcp_server-0.1.0/SECURITY.md +57 -0
  24. keycloak_mcp_server-0.1.0/compose.yaml +26 -0
  25. keycloak_mcp_server-0.1.0/deployment/openshift/buildconfig.yaml +29 -0
  26. keycloak_mcp_server-0.1.0/deployment/openshift/configmap.yaml +22 -0
  27. keycloak_mcp_server-0.1.0/deployment/openshift/deployment.yaml +69 -0
  28. keycloak_mcp_server-0.1.0/deployment/openshift/imagestream.yaml +10 -0
  29. keycloak_mcp_server-0.1.0/deployment/openshift/kustomization.yaml +16 -0
  30. keycloak_mcp_server-0.1.0/deployment/openshift/pvc.yaml +13 -0
  31. keycloak_mcp_server-0.1.0/deployment/openshift/route.yaml +16 -0
  32. keycloak_mcp_server-0.1.0/deployment/openshift/secret.yaml +14 -0
  33. keycloak_mcp_server-0.1.0/deployment/openshift/service.yaml +17 -0
  34. keycloak_mcp_server-0.1.0/docs/architecture.md +276 -0
  35. keycloak_mcp_server-0.1.0/docs/authentication.md +194 -0
  36. keycloak_mcp_server-0.1.0/docs/ci-cd.md +92 -0
  37. keycloak_mcp_server-0.1.0/docs/deployment.md +79 -0
  38. keycloak_mcp_server-0.1.0/docs/development.md +245 -0
  39. keycloak_mcp_server-0.1.0/docs/keycloak-tools.md +124 -0
  40. keycloak_mcp_server-0.1.0/docs/tutorial.md +201 -0
  41. keycloak_mcp_server-0.1.0/examples/README.md +106 -0
  42. keycloak_mcp_server-0.1.0/examples/fastmcp_client.py +109 -0
  43. keycloak_mcp_server-0.1.0/examples/keycloak_client.py +66 -0
  44. keycloak_mcp_server-0.1.0/examples/langgraph_client.py +247 -0
  45. keycloak_mcp_server-0.1.0/keycloak_mcp_server/__init__.py +3 -0
  46. keycloak_mcp_server-0.1.0/keycloak_mcp_server/py.typed +0 -0
  47. keycloak_mcp_server-0.1.0/keycloak_mcp_server/src/README.md +35 -0
  48. keycloak_mcp_server-0.1.0/keycloak_mcp_server/src/__init__.py +1 -0
  49. keycloak_mcp_server-0.1.0/keycloak_mcp_server/src/api.py +64 -0
  50. keycloak_mcp_server-0.1.0/keycloak_mcp_server/src/assets/README.md +83 -0
  51. keycloak_mcp_server-0.1.0/keycloak_mcp_server/src/keycloak_api/__init__.py +1 -0
  52. keycloak_mcp_server-0.1.0/keycloak_mcp_server/src/keycloak_api/auth.py +202 -0
  53. keycloak_mcp_server-0.1.0/keycloak_mcp_server/src/keycloak_api/service.py +190 -0
  54. keycloak_mcp_server-0.1.0/keycloak_mcp_server/src/main.py +144 -0
  55. keycloak_mcp_server-0.1.0/keycloak_mcp_server/src/mcp.py +54 -0
  56. keycloak_mcp_server-0.1.0/keycloak_mcp_server/src/settings.py +206 -0
  57. keycloak_mcp_server-0.1.0/keycloak_mcp_server/src/tools/README.md +84 -0
  58. keycloak_mcp_server-0.1.0/keycloak_mcp_server/src/tools/__init__.py +1 -0
  59. keycloak_mcp_server-0.1.0/keycloak_mcp_server/src/tools/keycloak_tools.py +593 -0
  60. keycloak_mcp_server-0.1.0/keycloak_mcp_server/utils/__init__.py +1 -0
  61. keycloak_mcp_server-0.1.0/keycloak_mcp_server/utils/pylogger.py +204 -0
  62. keycloak_mcp_server-0.1.0/pyproject.toml +125 -0
  63. keycloak_mcp_server-0.1.0/tests/README.md +129 -0
  64. keycloak_mcp_server-0.1.0/tests/conftest.py +163 -0
  65. keycloak_mcp_server-0.1.0/tests/test_api.py +160 -0
  66. keycloak_mcp_server-0.1.0/tests/test_auth_discovery.py +63 -0
  67. keycloak_mcp_server-0.1.0/tests/test_basic.py +299 -0
  68. keycloak_mcp_server-0.1.0/tests/test_keycloak.py +469 -0
  69. keycloak_mcp_server-0.1.0/tests/test_keycloak_oauth.py +417 -0
  70. keycloak_mcp_server-0.1.0/tests/test_main.py +307 -0
  71. keycloak_mcp_server-0.1.0/tests/test_mcp.py +128 -0
  72. keycloak_mcp_server-0.1.0/tests/test_settings.py +159 -0
  73. keycloak_mcp_server-0.1.0/tests/test_utils.py +580 -0
  74. keycloak_mcp_server-0.1.0/uv.lock +3220 -0
@@ -0,0 +1,43 @@
1
+ # Git and version control
2
+ .git/
3
+ .gitignore
4
+ .gitlab-ci.yml
5
+
6
+ # Python cache and build artifacts
7
+ __pycache__/
8
+ *.py[cod]
9
+ *$py.class
10
+ .pytest_cache/
11
+ *.egg-info/
12
+ build/
13
+ dist/
14
+
15
+ # IDE and editor files
16
+ .cursor/
17
+ .vscode/
18
+ *.swp
19
+ *.swo
20
+ *~
21
+
22
+ # Development and documentation
23
+ LICENSE
24
+ Makefile
25
+ .pre-commit-config.yaml
26
+
27
+ # OS generated files
28
+ .DS_Store
29
+ .DS_Store?
30
+ ._*
31
+ Thumbs.db
32
+
33
+ # Local environment, credentials, and OAuth state
34
+ .env
35
+ .venv/
36
+ .keycloak-oauth/
37
+
38
+ # Test files (optional - remove if you want tests in container)
39
+ tests/
40
+
41
+ # Container files themselves
42
+ Containerfile
43
+ .containerignore
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "Keycloak MCP Server",
3
+ "image": "mcr.microsoft.com/devcontainers/python:3.12",
4
+ "postCreateCommand": "curl -LsSf https://astral.sh/uv/install.sh | sh && \"$HOME/.local/bin/uv\" sync --locked && \"$HOME/.local/bin/uv\" run --locked pre-commit install && if [ ! -f .env ]; then cp .env.example .env; fi",
5
+ "customizations": {
6
+ "vscode": {
7
+ "settings": {
8
+ "python.defaultInterpreterPath": ".venv/bin/python",
9
+ "python.terminal.activateEnvironment": false,
10
+ "[python]": {
11
+ "editor.defaultFormatter": "charliermarsh.ruff",
12
+ "editor.formatOnSave": true
13
+ }
14
+ },
15
+ "extensions": [
16
+ "charliermarsh.ruff",
17
+ "ms-python.python",
18
+ "ms-python.mypy-type-checker",
19
+ "ms-python.debugpy",
20
+ "tamasfe.even-better-toml"
21
+ ]
22
+ }
23
+ },
24
+ "forwardPorts": [
25
+ 5001
26
+ ],
27
+ "containerEnv": {
28
+ "PYTHONPATH": "${containerWorkspaceFolder}"
29
+ },
30
+ "remoteEnv": {
31
+ "PATH": "${containerEnv:HOME}/.local/bin:${containerEnv:PATH}"
32
+ }
33
+ }
@@ -0,0 +1,35 @@
1
+ # Copy to .env. Discovery-only mode works without Keycloak credentials.
2
+ MCP_HOST=localhost
3
+ MCP_PORT=5001
4
+ MCP_HOST_ENDPOINT=http://localhost:5001
5
+ # http and streamable-http both use /mcp; sse is the legacy /sse transport.
6
+ MCP_TRANSPORT_PROTOCOL=http
7
+ ENABLE_AUTH=False
8
+ ENVIRONMENT=development
9
+ PYTHON_LOG_LEVEL=INFO
10
+
11
+ # For browser OAuth, enable ENABLE_AUTH and configure the persistent signing key.
12
+ # Register a public keycloak-mcp client in your realm, with redirect:
13
+ # http://localhost:5001/auth/callback (see docs/authentication.md)
14
+ # Base URL before /realms; legacy WildFly distributions add /auth.
15
+ KEYCLOAK_SERVER_URL=https://keycloak.example.com
16
+ KEYCLOAK_REALM=myrealm
17
+ KEYCLOAK_OAUTH_CLIENT_ID=keycloak-mcp
18
+ # Public client: no Keycloak client secret.
19
+ # Optional only for a confidential upstream client:
20
+ # KEYCLOAK_OAUTH_CLIENT_SECRET=
21
+ # Generate once: uv run python -c 'import secrets; print(secrets.token_urlsafe(48))'
22
+ # KEYCLOAK_OAUTH_SIGNING_KEY=
23
+ # Add an audience mapper for the client's own ID and require it here.
24
+ KEYCLOAK_OAUTH_AUDIENCE=keycloak-mcp
25
+ KEYCLOAK_OAUTH_SCOPES="openid profile email"
26
+ KEYCLOAK_OAUTH_STORAGE_DIR=.keycloak-oauth
27
+ KEYCLOAK_TIMEOUT=30
28
+ # TLS verification stays enabled; use a PEM bundle for internal certificate issuers.
29
+ # KEYCLOAK_CA_BUNDLE=/path/to/trusted-ca-bundle.pem
30
+ # Downstream clients use random loopback callback ports; these defaults allow them.
31
+ # KEYCLOAK_OAUTH_CLIENT_REDIRECT_URIS=["http://localhost:*/*","http://127.0.0.1:*/*"]
32
+
33
+ # Optional single-user localhost shortcut with ENABLE_AUTH=False only.
34
+ # Must be removed before enabling OAuth. No service-account login is performed.
35
+ # KEYCLOAK_DEV_ACCESS_TOKEN=
@@ -0,0 +1,101 @@
1
+ name: Bug Report
2
+ description: Report a bug or unexpected behavior.
3
+ title: "[Bug]: "
4
+ labels: ["type/bug", "status/triage"]
5
+ body:
6
+ - type: markdown
7
+ attributes:
8
+ value: |
9
+ Thanks for reporting a bug! Please fill out the sections below so we can reproduce and fix it.
10
+
11
+ - type: textarea
12
+ id: description
13
+ attributes:
14
+ label: Describe the bug
15
+ description: A clear and concise description of what the bug is.
16
+ placeholder: When I call the multiply tool with...
17
+ validations:
18
+ required: true
19
+
20
+ - type: textarea
21
+ id: steps
22
+ attributes:
23
+ label: Steps to reproduce
24
+ description: Minimal steps to reproduce the behavior.
25
+ placeholder: |
26
+ 1. Start the server with `make local`
27
+ 2. Send a request to `/mcp` with payload...
28
+ 3. Observe the error...
29
+ validations:
30
+ required: true
31
+
32
+ - type: textarea
33
+ id: expected
34
+ attributes:
35
+ label: Expected behavior
36
+ description: What did you expect to happen?
37
+ validations:
38
+ required: true
39
+
40
+ - type: textarea
41
+ id: actual
42
+ attributes:
43
+ label: Actual behavior
44
+ description: What actually happened? Include error messages or logs if available.
45
+ validations:
46
+ required: true
47
+
48
+ - type: input
49
+ id: version
50
+ attributes:
51
+ label: Version
52
+ description: Which version of the server are you running?
53
+ placeholder: "0.1.0"
54
+ validations:
55
+ required: true
56
+
57
+ - type: dropdown
58
+ id: transport
59
+ attributes:
60
+ label: Transport protocol
61
+ description: Which transport protocol are you using?
62
+ options:
63
+ - streamable-http
64
+ - sse
65
+ - http
66
+ - Not applicable
67
+ validations:
68
+ required: true
69
+
70
+ - type: textarea
71
+ id: environment
72
+ attributes:
73
+ label: Environment
74
+ description: |
75
+ Provide details about your environment.
76
+ placeholder: |
77
+ - OS: macOS 15.2 / Ubuntu 24.04 / etc.
78
+ - Python: 3.12.2
79
+ - Deployment: local / container / OpenShift
80
+ render: markdown
81
+ validations:
82
+ required: false
83
+
84
+ - type: textarea
85
+ id: logs
86
+ attributes:
87
+ label: Relevant logs
88
+ description: Paste any relevant log output. This will be formatted as code automatically.
89
+ render: shell
90
+ validations:
91
+ required: false
92
+
93
+ - type: checkboxes
94
+ id: checklist
95
+ attributes:
96
+ label: Checklist
97
+ options:
98
+ - label: I searched existing issues and this is not a duplicate.
99
+ required: true
100
+ - label: I am using a supported Python version (3.12+).
101
+ required: false
@@ -0,0 +1,8 @@
1
+ blank_issues_enabled: false
2
+ contact_links:
3
+ - name: Questions & Discussions
4
+ url: https://github.com/drtinkerer/keycloak-mcp-server/discussions
5
+ about: Ask questions, share ideas, or discuss the project.
6
+ - name: Security Vulnerabilities
7
+ url: https://github.com/drtinkerer/keycloak-mcp-server/security/advisories/new
8
+ about: Report security vulnerabilities privately (do NOT use public issues).
@@ -0,0 +1,79 @@
1
+ name: Feature Request
2
+ description: Suggest a new feature or improvement.
3
+ title: "[Feature]: "
4
+ labels: ["type/feature", "status/triage"]
5
+ body:
6
+ - type: markdown
7
+ attributes:
8
+ value: |
9
+ Thanks for suggesting a feature! Please describe the problem and your proposed solution.
10
+
11
+ - type: textarea
12
+ id: problem
13
+ attributes:
14
+ label: Problem statement
15
+ description: What problem are you trying to solve? What's the use case?
16
+ placeholder: I'm always frustrated when...
17
+ validations:
18
+ required: true
19
+
20
+ - type: textarea
21
+ id: solution
22
+ attributes:
23
+ label: Proposed solution
24
+ description: Describe the solution you'd like.
25
+ placeholder: I would like the server to...
26
+ validations:
27
+ required: true
28
+
29
+ - type: textarea
30
+ id: alternatives
31
+ attributes:
32
+ label: Alternatives considered
33
+ description: Any alternative solutions or workarounds you've considered?
34
+ validations:
35
+ required: false
36
+
37
+ - type: dropdown
38
+ id: area
39
+ attributes:
40
+ label: Area
41
+ description: Which part of the project does this relate to?
42
+ options:
43
+ - MCP Tools
44
+ - Server Core
45
+ - OAuth / Authentication
46
+ - Storage
47
+ - Deployment / Infrastructure
48
+ - CI/CD
49
+ - Documentation
50
+ - Other
51
+ validations:
52
+ required: true
53
+
54
+ - type: dropdown
55
+ id: priority
56
+ attributes:
57
+ label: How important is this to you?
58
+ options:
59
+ - Nice to have
60
+ - Important - affects my workflow
61
+ - Critical - blocking my use case
62
+ validations:
63
+ required: true
64
+
65
+ - type: textarea
66
+ id: context
67
+ attributes:
68
+ label: Additional context
69
+ description: Any other context, screenshots, or examples.
70
+ validations:
71
+ required: false
72
+
73
+ - type: checkboxes
74
+ id: contribution
75
+ attributes:
76
+ label: Contribution
77
+ options:
78
+ - label: I would be willing to submit a PR for this feature.
79
+ required: false
@@ -0,0 +1,36 @@
1
+ ## Description
2
+
3
+ <!-- Briefly describe what this PR does and why. -->
4
+
5
+ ## Related Issues
6
+
7
+ <!-- Link related issues: Closes #123, Fixes #456 -->
8
+
9
+ ## Type of Change
10
+
11
+ - [ ] Bug fix (non-breaking change that fixes an issue)
12
+ - [ ] New feature (non-breaking change that adds functionality)
13
+ - [ ] Breaking change (fix or feature that would cause existing functionality to change)
14
+ - [ ] Documentation update
15
+ - [ ] Refactoring (no functional changes)
16
+ - [ ] CI/CD or infrastructure change
17
+ - [ ] Dependency update
18
+
19
+ ## Checklist
20
+
21
+ - [ ] My code follows the project's coding standards (Ruff, MyPy, pydocstyle)
22
+ - [ ] I have added tests that prove my fix is effective or my feature works
23
+ - [ ] All new and existing tests pass (`make test`)
24
+ - [ ] Pre-commit hooks pass (`make pre-commit`)
25
+ - [ ] Code coverage remains >= 80% (`make coverage`)
26
+ - [ ] I have updated documentation where necessary
27
+ - [ ] I have updated `CHANGELOG.md` (if applicable)
28
+ - [ ] My PR title follows [Conventional Commits](https://www.conventionalcommits.org/) format
29
+
30
+ ## Testing
31
+
32
+ <!-- Describe how you tested your changes. -->
33
+
34
+ ## Screenshots / Logs
35
+
36
+ <!-- If applicable, add screenshots or log output. -->
@@ -0,0 +1,32 @@
1
+ version: 2
2
+
3
+ updates:
4
+ # Python dependencies (pip)
5
+ - package-ecosystem: "pip"
6
+ directory: "/"
7
+ schedule:
8
+ interval: "weekly"
9
+ day: "monday"
10
+ open-pull-requests-limit: 10
11
+ labels:
12
+ - "type/dependency"
13
+ - "area/python"
14
+ commit-message:
15
+ prefix: "build(deps):"
16
+ reviewers:
17
+ - "drtinkerer"
18
+
19
+ # GitHub Actions
20
+ - package-ecosystem: "github-actions"
21
+ directory: "/"
22
+ schedule:
23
+ interval: "weekly"
24
+ day: "monday"
25
+ open-pull-requests-limit: 5
26
+ labels:
27
+ - "type/dependency"
28
+ - "area/ci"
29
+ commit-message:
30
+ prefix: "ci(deps):"
31
+ reviewers:
32
+ - "drtinkerer"
@@ -0,0 +1,35 @@
1
+ name: Pre-commit
2
+
3
+ on:
4
+ push:
5
+ branches: [ main ]
6
+ pull_request:
7
+ branches: [ main ]
8
+
9
+ concurrency:
10
+ group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
11
+ cancel-in-progress: ${{ github.event_name == 'pull_request' }}
12
+
13
+ env:
14
+ PYTHON_VERSION: "3.12"
15
+
16
+ jobs:
17
+ pre-commit:
18
+ name: Pre Commit
19
+ runs-on: ubuntu-latest
20
+
21
+ steps:
22
+ - name: Checkout code
23
+ uses: actions/checkout@v4
24
+
25
+ - name: Install uv
26
+ uses: astral-sh/setup-uv@v3
27
+ with:
28
+ version: "latest"
29
+
30
+ - name: Install locked dependencies
31
+ run: uv sync --locked --python ${{ env.PYTHON_VERSION }}
32
+
33
+ - name: Run Pre Commit
34
+ run: |
35
+ uv run --locked pre-commit run --all-files
@@ -0,0 +1,89 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+ workflow_dispatch:
7
+ inputs:
8
+ publish_to_test:
9
+ description: 'Publish to Test PyPI instead of PyPI'
10
+ required: false
11
+ default: false
12
+ type: boolean
13
+
14
+ permissions:
15
+ contents: read
16
+
17
+ jobs:
18
+ build:
19
+ runs-on: ubuntu-latest
20
+ steps:
21
+ - uses: actions/checkout@v4
22
+
23
+ - name: Install uv
24
+ uses: astral-sh/setup-uv@v3
25
+
26
+ - name: Check release tag matches package version
27
+ if: github.event_name == 'release'
28
+ run: |
29
+ version=$(uv version --short)
30
+ if [ "${{ github.event.release.tag_name }}" != "v${version}" ]; then
31
+ echo "Release tag ${{ github.event.release.tag_name }} does not match pyproject version v${version}"
32
+ exit 1
33
+ fi
34
+
35
+ - name: Build package
36
+ run: uv build
37
+
38
+ - name: Check package
39
+ run: uvx twine check dist/*
40
+
41
+ - name: Upload build artifacts
42
+ uses: actions/upload-artifact@v4
43
+ with:
44
+ name: dist
45
+ path: dist/
46
+
47
+ test:
48
+ runs-on: ubuntu-latest
49
+ strategy:
50
+ matrix:
51
+ python-version: ['3.12', '3.13']
52
+ steps:
53
+ - uses: actions/checkout@v4
54
+
55
+ - name: Install uv
56
+ uses: astral-sh/setup-uv@v3
57
+
58
+ - name: Install locked dependencies
59
+ run: uv sync --locked --python ${{ matrix.python-version }}
60
+
61
+ - name: Run tests
62
+ env:
63
+ ENABLE_AUTH: "False"
64
+ run: uv run --locked pytest --cov=keycloak_mcp_server --cov-report=term-missing
65
+
66
+ publish:
67
+ needs: [build, test]
68
+ runs-on: ubuntu-latest
69
+ environment:
70
+ name: ${{ github.event.inputs.publish_to_test == 'true' && 'test-pypi' || 'pypi' }}
71
+ url: ${{ github.event.inputs.publish_to_test == 'true' && 'https://test.pypi.org/p/keycloak-mcp-server' || 'https://pypi.org/p/keycloak-mcp-server' }}
72
+ permissions:
73
+ id-token: write # Required for PyPI trusted publishing
74
+ steps:
75
+ - name: Download build artifacts
76
+ uses: actions/download-artifact@v4
77
+ with:
78
+ name: dist
79
+ path: dist/
80
+
81
+ - name: Publish to Test PyPI
82
+ if: github.event.inputs.publish_to_test == 'true'
83
+ uses: pypa/gh-action-pypi-publish@release/v1
84
+ with:
85
+ repository-url: https://test.pypi.org/legacy/
86
+
87
+ - name: Publish to PyPI
88
+ if: github.event.inputs.publish_to_test != 'true'
89
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,46 @@
1
+ name: Stale Issues and PRs
2
+
3
+ on:
4
+ schedule:
5
+ - cron: "0 9 * * 1" # Every Monday at 9:00 UTC
6
+ workflow_dispatch:
7
+
8
+ concurrency:
9
+ group: ${{ github.workflow }}
10
+ cancel-in-progress: false
11
+
12
+ permissions:
13
+ issues: write
14
+ pull-requests: write
15
+
16
+ jobs:
17
+ stale:
18
+ name: Close stale issues and PRs
19
+ runs-on: ubuntu-latest
20
+ steps:
21
+ - uses: actions/stale@v11
22
+ with:
23
+ stale-issue-message: >
24
+ This issue has been automatically marked as stale because it has not
25
+ had activity in the last 60 days. It will be closed in 14 days if no
26
+ further activity occurs. If this issue is still relevant, please
27
+ comment or remove the stale label.
28
+ stale-pr-message: >
29
+ This pull request has been automatically marked as stale because it
30
+ has not had activity in the last 30 days. It will be closed in 14
31
+ days if no further activity occurs. If this PR is still in progress,
32
+ please comment or push new commits.
33
+ close-issue-message: >
34
+ This issue was closed because it has been stale for 14 days with no
35
+ activity. Feel free to reopen if still relevant.
36
+ close-pr-message: >
37
+ This pull request was closed because it has been stale for 14 days
38
+ with no activity. Feel free to reopen if still relevant.
39
+ days-before-issue-stale: 60
40
+ days-before-pr-stale: 30
41
+ days-before-issue-close: 14
42
+ days-before-pr-close: 14
43
+ stale-issue-label: "status/stale"
44
+ stale-pr-label: "status/stale"
45
+ exempt-issue-labels: "priority/high,status/blocked,good first issue"
46
+ exempt-pr-labels: "priority/high,status/blocked"
@@ -0,0 +1,47 @@
1
+ name: Tests
2
+
3
+ on:
4
+ push:
5
+ branches: [ main ]
6
+ pull_request:
7
+ branches: [ main ]
8
+
9
+ concurrency:
10
+ group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
11
+ cancel-in-progress: ${{ github.event_name == 'pull_request' }}
12
+
13
+ jobs:
14
+ test:
15
+ name: Test Suite
16
+ runs-on: ubuntu-latest
17
+ strategy:
18
+ matrix:
19
+ python-version: ["3.12", "3.13"]
20
+
21
+ steps:
22
+ - name: Checkout code
23
+ uses: actions/checkout@v4
24
+
25
+ - name: Install uv
26
+ uses: astral-sh/setup-uv@v3
27
+ with:
28
+ version: "latest"
29
+
30
+ - name: Install locked dependencies
31
+ run: uv sync --locked --python ${{ matrix.python-version }}
32
+
33
+ - name: Run tests with coverage
34
+ env:
35
+ ENABLE_AUTH: "False"
36
+ run: |
37
+ uv run --locked pytest --cov=keycloak_mcp_server --cov-report=xml --cov-report=term-missing --cov-fail-under=80
38
+
39
+ - name: Upload coverage reports to Codecov
40
+ uses: codecov/codecov-action@v4
41
+ with:
42
+ file: ./coverage.xml
43
+ flags: unittests
44
+ name: codecov-umbrella
45
+ fail_ci_if_error: false
46
+ env:
47
+ CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
@@ -0,0 +1,71 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ dist/
13
+ eggs/
14
+ .eggs/
15
+ *.egg-info/
16
+ *.egg
17
+ MANIFEST
18
+
19
+ # Unit test / coverage reports
20
+ htmlcov/
21
+ .tox/
22
+ .nox/
23
+ .coverage
24
+ .coverage.*
25
+ .cache
26
+ coverage.xml
27
+ *.cover
28
+ *.py,cover
29
+ .hypothesis/
30
+ .pytest_cache/
31
+
32
+ # Environments
33
+ .env
34
+ .keycloak-oauth/
35
+ .venv
36
+ env/
37
+ venv/
38
+
39
+ # mypy
40
+ .mypy_cache/
41
+ .dmypy.json
42
+ dmypy.json
43
+
44
+ # Ruff
45
+ .ruff_cache/
46
+
47
+ # pytype
48
+ .pytype/
49
+
50
+ # IDE files
51
+ .cursor/
52
+ .vscode/
53
+ .idea/
54
+ *.swp
55
+ *.swo
56
+ *~
57
+
58
+ # OS generated files
59
+ .DS_Store
60
+ Thumbs.db
61
+
62
+ # Logs
63
+ *.log
64
+
65
+ # Project-specific
66
+ bandit-report.json
67
+ safety-report.json
68
+ .safety-project.ini
69
+ build.log
70
+ *.tmp
71
+ *.bak