notebook-intelligence 2.4.2__tar.gz → 2.5.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 (72) hide show
  1. {notebook_intelligence-2.4.2 → notebook_intelligence-2.5.0}/.gitignore +8 -0
  2. {notebook_intelligence-2.4.2 → notebook_intelligence-2.5.0}/PKG-INFO +18 -112
  3. {notebook_intelligence-2.4.2 → notebook_intelligence-2.5.0}/README.md +17 -111
  4. {notebook_intelligence-2.4.2 → notebook_intelligence-2.5.0}/notebook_intelligence/_version.py +1 -1
  5. {notebook_intelligence-2.4.2 → notebook_intelligence-2.5.0}/notebook_intelligence/ai_service_manager.py +23 -0
  6. {notebook_intelligence-2.4.2 → notebook_intelligence-2.5.0}/notebook_intelligence/api.py +18 -5
  7. {notebook_intelligence-2.4.2 → notebook_intelligence-2.5.0}/notebook_intelligence/config.py +19 -0
  8. {notebook_intelligence-2.4.2 → notebook_intelligence-2.5.0}/notebook_intelligence/extension.py +31 -16
  9. {notebook_intelligence-2.4.2 → notebook_intelligence-2.5.0}/notebook_intelligence/labextension/package.json +2 -2
  10. {notebook_intelligence-2.4.2 → notebook_intelligence-2.5.0}/notebook_intelligence/labextension/schemas/@notebook-intelligence/notebook-intelligence/package.json.orig +1 -1
  11. notebook_intelligence-2.5.0/notebook_intelligence/labextension/static/710.48e0d2ef1ca25852bd40.js +1 -0
  12. notebook_intelligence-2.4.2/notebook_intelligence/labextension/static/728.e21c211a709fe0ab1e1f.js → notebook_intelligence-2.5.0/notebook_intelligence/labextension/static/728.0aa3e2924c9bfe4d8d30.js +1 -1
  13. notebook_intelligence-2.5.0/notebook_intelligence/labextension/static/editor.worker.js +1407 -0
  14. notebook_intelligence-2.4.2/notebook_intelligence/labextension/static/remoteEntry.d9d709f6862dfa2e5a69.js → notebook_intelligence-2.5.0/notebook_intelligence/labextension/static/remoteEntry.84c6d4df1ff766bc53bf.js +1 -1
  15. {notebook_intelligence-2.4.2 → notebook_intelligence-2.5.0}/notebook_intelligence/mcp_manager.py +219 -22
  16. notebook_intelligence-2.5.0/notebook_intelligence/rule_manager.py +224 -0
  17. notebook_intelligence-2.5.0/notebook_intelligence/ruleset.py +259 -0
  18. {notebook_intelligence-2.4.2 → notebook_intelligence-2.5.0}/package.json +1 -1
  19. notebook_intelligence-2.5.0/tests/conftest.py +168 -0
  20. notebook_intelligence-2.5.0/tests/fixtures/rules/01-test-global.md +17 -0
  21. notebook_intelligence-2.5.0/tests/fixtures/rules/02-test-security.md +15 -0
  22. notebook_intelligence-2.5.0/tests/fixtures/rules/03-invalid-rule.md +11 -0
  23. notebook_intelligence-2.5.0/tests/fixtures/rules/modes/agent/01-test-production.md +15 -0
  24. notebook_intelligence-2.5.0/tests/fixtures/rules/modes/ask/01-test-exploration.md +13 -0
  25. notebook_intelligence-2.5.0/tests/fixtures/rules/modes/inline-chat/01-test-quick.md +14 -0
  26. notebook_intelligence-2.5.0/tests/test_config_integration.py +116 -0
  27. notebook_intelligence-2.5.0/tests/test_models.py +402 -0
  28. notebook_intelligence-2.5.0/tests/test_rule_manager.py +312 -0
  29. {notebook_intelligence-2.4.2 → notebook_intelligence-2.5.0}/tsconfig.json +1 -1
  30. notebook_intelligence-2.4.2/notebook_intelligence/labextension/static/144.3ed487e60baf9785fae1.js +0 -1
  31. notebook_intelligence-2.4.2/notebook_intelligence/labextension/static/editor.worker.js +0 -1407
  32. {notebook_intelligence-2.4.2 → notebook_intelligence-2.5.0}/.copier-answers.yml +0 -0
  33. {notebook_intelligence-2.4.2 → notebook_intelligence-2.5.0}/.prettierignore +0 -0
  34. {notebook_intelligence-2.4.2 → notebook_intelligence-2.5.0}/.yarnrc.yml +0 -0
  35. {notebook_intelligence-2.4.2 → notebook_intelligence-2.5.0}/CHANGELOG.md +0 -0
  36. {notebook_intelligence-2.4.2 → notebook_intelligence-2.5.0}/CONTRIBUTING.md +0 -0
  37. {notebook_intelligence-2.4.2 → notebook_intelligence-2.5.0}/LICENSE +0 -0
  38. {notebook_intelligence-2.4.2 → notebook_intelligence-2.5.0}/RELEASE.md +0 -0
  39. {notebook_intelligence-2.4.2 → notebook_intelligence-2.5.0}/install.json +0 -0
  40. {notebook_intelligence-2.4.2 → notebook_intelligence-2.5.0}/jupyter-config/server-config/notebook_intelligence.json +0 -0
  41. {notebook_intelligence-2.4.2 → notebook_intelligence-2.5.0}/notebook_intelligence/__init__.py +0 -0
  42. {notebook_intelligence-2.4.2 → notebook_intelligence-2.5.0}/notebook_intelligence/base_chat_participant.py +0 -0
  43. {notebook_intelligence-2.4.2 → notebook_intelligence-2.5.0}/notebook_intelligence/built_in_toolsets.py +0 -0
  44. {notebook_intelligence-2.4.2 → notebook_intelligence-2.5.0}/notebook_intelligence/github_copilot.py +0 -0
  45. {notebook_intelligence-2.4.2 → notebook_intelligence-2.5.0}/notebook_intelligence/github_copilot_chat_participant.py +0 -0
  46. {notebook_intelligence-2.4.2 → notebook_intelligence-2.5.0}/notebook_intelligence/labextension/schemas/@notebook-intelligence/notebook-intelligence/plugin.json +0 -0
  47. {notebook_intelligence-2.4.2 → notebook_intelligence-2.5.0}/notebook_intelligence/labextension/static/196.db3f5562c0372c6e07f6.js +0 -0
  48. {notebook_intelligence-2.4.2 → notebook_intelligence-2.5.0}/notebook_intelligence/labextension/static/1b55f12eca93ba6743e7.ttf +0 -0
  49. {notebook_intelligence-2.4.2 → notebook_intelligence-2.5.0}/notebook_intelligence/labextension/static/326.4de77f44c9c6c2bbad47.js +0 -0
  50. {notebook_intelligence-2.4.2 → notebook_intelligence-2.5.0}/notebook_intelligence/labextension/static/326.4de77f44c9c6c2bbad47.js.LICENSE.txt +0 -0
  51. {notebook_intelligence-2.4.2 → notebook_intelligence-2.5.0}/notebook_intelligence/labextension/static/327.fe6b84491254fcaf64bf.js +0 -0
  52. {notebook_intelligence-2.4.2 → notebook_intelligence-2.5.0}/notebook_intelligence/labextension/static/327.fe6b84491254fcaf64bf.js.LICENSE.txt +0 -0
  53. {notebook_intelligence-2.4.2 → notebook_intelligence-2.5.0}/notebook_intelligence/labextension/static/671.1797d409270b24758991.js +0 -0
  54. {notebook_intelligence-2.4.2 → notebook_intelligence-2.5.0}/notebook_intelligence/labextension/static/694.d0b052d80c0397c7f1ea.js +0 -0
  55. {notebook_intelligence-2.4.2 → notebook_intelligence-2.5.0}/notebook_intelligence/labextension/static/830.46ab52f7b558fb3c1a20.js +0 -0
  56. {notebook_intelligence-2.4.2 → notebook_intelligence-2.5.0}/notebook_intelligence/labextension/static/977.7e3d66ffc344a0af7a4e.js +0 -0
  57. {notebook_intelligence-2.4.2 → notebook_intelligence-2.5.0}/notebook_intelligence/labextension/static/be02dcbf2787b0b29ec8.module.wasm +0 -0
  58. {notebook_intelligence-2.4.2 → notebook_intelligence-2.5.0}/notebook_intelligence/labextension/static/e589c9ba04e3e5a90081.module.wasm +0 -0
  59. {notebook_intelligence-2.4.2 → notebook_intelligence-2.5.0}/notebook_intelligence/labextension/static/editor.worker.js.LICENSE.txt +0 -0
  60. {notebook_intelligence-2.4.2 → notebook_intelligence-2.5.0}/notebook_intelligence/labextension/static/style.js +0 -0
  61. {notebook_intelligence-2.4.2 → notebook_intelligence-2.5.0}/notebook_intelligence/labextension/static/third-party-licenses.json +0 -0
  62. {notebook_intelligence-2.4.2 → notebook_intelligence-2.5.0}/notebook_intelligence/llm_providers/github_copilot_llm_provider.py +0 -0
  63. {notebook_intelligence-2.4.2 → notebook_intelligence-2.5.0}/notebook_intelligence/llm_providers/litellm_compatible_llm_provider.py +0 -0
  64. {notebook_intelligence-2.4.2 → notebook_intelligence-2.5.0}/notebook_intelligence/llm_providers/ollama_llm_provider.py +0 -0
  65. {notebook_intelligence-2.4.2 → notebook_intelligence-2.5.0}/notebook_intelligence/llm_providers/openai_compatible_llm_provider.py +0 -0
  66. {notebook_intelligence-2.4.2 → notebook_intelligence-2.5.0}/notebook_intelligence/prompts.py +0 -0
  67. {notebook_intelligence-2.4.2 → notebook_intelligence-2.5.0}/notebook_intelligence/util.py +0 -0
  68. {notebook_intelligence-2.4.2 → notebook_intelligence-2.5.0}/pyproject.toml +0 -0
  69. {notebook_intelligence-2.4.2 → notebook_intelligence-2.5.0}/schema/plugin.json +0 -0
  70. {notebook_intelligence-2.4.2 → notebook_intelligence-2.5.0}/setup.py +0 -0
  71. {notebook_intelligence-2.4.2 → notebook_intelligence-2.5.0}/webpack.config.js +0 -0
  72. {notebook_intelligence-2.4.2 → notebook_intelligence-2.5.0}/yarn.lock +0 -0
@@ -83,6 +83,14 @@ target/
83
83
  # pyenv
84
84
  .python-version
85
85
 
86
+ # Virtual environments
87
+ venv/
88
+ env/
89
+ ENV/
90
+ .venv/
91
+ .env/
92
+ venv*/
93
+ .vscode/
86
94
  # celery beat schedule file
87
95
  celerybeat-schedule
88
96
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: notebook_intelligence
3
- Version: 2.4.2
3
+ Version: 2.5.0
4
4
  Summary: AI coding assistant for JupyterLab
5
5
  Project-URL: Homepage, https://github.com/notebook-intelligence/notebook-intelligence
6
6
  Project-URL: Bug Tracker, https://github.com/notebook-intelligence/notebook-intelligence/issues
@@ -801,18 +801,18 @@ jupyter lab --NotebookIntelligence.notebook_execute_tool=env_enabled
801
801
 
802
802
  ### Configuration files
803
803
 
804
- NBI saves configuration at `~/.jupyter/nbi-config.json`. It also supports environment wide base configuration at `<env-prefix>/share/jupyter/nbi-config.json`. Organizations can ship default configuration at this environment wide config path. User's changes will be stored as overrides at `~/.jupyter/nbi-config.json`.
804
+ NBI saves configuration at `~/.jupyter/nbi/config.json`. It also supports environment wide base configuration at `<env-prefix>/share/jupyter/nbi/config.json`. Organizations can ship default configuration at this environment wide config path. User's changes will be stored as overrides at `~/.jupyter/nbi/config.json`.
805
805
 
806
806
  These config files are used for saving LLM provider, model and MCP configuration. Note that API keys you enter for your custom LLM providers will also be stored in these config files.
807
807
 
808
808
  > [!IMPORTANT]
809
- > Note that updating nbi-config.json manually requires restarting JupyterLab to take effect.
809
+ > Note that updating config.json manually requires restarting JupyterLab to take effect.
810
810
 
811
811
  ### Model Context Protocol ([MCP](https://modelcontextprotocol.io)) Support
812
812
 
813
813
  NBI seamlessly integrates with MCP servers. It supports servers with both Standard Input/Output (stdio) and Server-Sent Events (SSE) transports. The MCP support is limited to server tools at the moment.
814
814
 
815
- You can easily add MCP servers to NBI by editing the configuration file [nbi-config.json](#configuration-files). Simply add a key "mcp" and "mcpServers" under it as shown below.
815
+ You can easily add MCP servers to NBI by editing the configuration file [~/.jupyter/nbi/mcp.json](#configuration-files). Environment wide base configuration is also support using the file at `<env-prefix>/share/jupyter/nbi/mcp.json`.
816
816
 
817
817
  > [!NOTE]
818
818
  > Using MCP servers requires an LLM model with tool calling capabilities. All of the GitHub Copilot models provided in NBI support this feature. If you are using other providers make sure you choose a tool calling capable model.
@@ -820,47 +820,24 @@ You can easily add MCP servers to NBI by editing the configuration file [nbi-con
820
820
  > [!CAUTION]
821
821
  > Note that most MCP servers are run on the same computer as your JupyterLab installation and they can make irreversible changes to your computer and/or access private data. Make sure that you only install MCP servers from trusted sources.
822
822
 
823
+ ### MCP Config file example
824
+
823
825
  ```json
824
826
  {
825
- "chat_model": {
826
- ...
827
- },
828
- ...<other configuration>,
829
-
830
- "mcp": {
831
- "mcpServers": {
832
- "filesystem": {
833
- "command": "npx",
834
- "args": [
835
- "-y",
836
- "@modelcontextprotocol/server-filesystem",
837
- "/Users/mbektas/mcp-test"
838
- ]
839
- },
840
- }
827
+ "mcpServers": {
828
+ "filesystem": {
829
+ "command": "npx",
830
+ "args": [
831
+ "-y",
832
+ "@modelcontextprotocol/server-filesystem",
833
+ "/Users/mbektas/mcp-test"
834
+ ]
841
835
  }
836
+ }
842
837
  }
843
838
  ```
844
839
 
845
- This will automatically create a new chat participant in NBI and you can access it by starting your prompts with `@mcp`. Use `@mcp /info` prompt to get information on the tools provided by the MCP servers you configured. This chat participant will have access all the tools provided by the servers you configure.
846
-
847
- <img src="media/mcp-prompt.png" alt="Settings dialog" width=600 />
848
-
849
- By default, each tool call to MCP servers will require approval. If you would like to auto approve tools, you can do so by using the `"alwaysAllow": []` configuration key in the nbi-config.json. Simply list the names of tools.
850
-
851
- ```json
852
- "mcpServers": {
853
- "filesystem": {
854
- "command": "npx",
855
- "args": [
856
- "-y",
857
- "@modelcontextprotocol/server-filesystem",
858
- "/Users/mbektas/mcp-test"
859
- ],
860
- "alwaysAllow": ["list_allowed_directories", "list_directory"]
861
- },
862
- }
863
- ```
840
+ You can use Agent mode to access tools provided by MCP servers you configured.
864
841
 
865
842
  For servers with stdio transport, you can also set additional environment variables by using the `env` key. Environment variables are specified as key value pairs.
866
843
 
@@ -876,12 +853,12 @@ For servers with stdio transport, you can also set additional environment variab
876
853
  }
877
854
  ```
878
855
 
879
- Below is an example of a server configuration with SSE transport. For SSE transport servers, you can also specify headers to be sent as part of the requests.
856
+ Below is an example of a server configuration with Streamable HTTP transport. For Streamable HTTP transport servers, you can also specify headers to be sent as part of the requests.
880
857
 
881
858
  ```json
882
859
  "mcpServers": {
883
860
  "remoterservername": {
884
- "url": "http://127.0.0.1:8080/sse",
861
+ "url": "http://127.0.0.1:8080/mcp",
885
862
  "headers": {
886
863
  "Authorization": "Bearer mysecrettoken"
887
864
  }
@@ -905,77 +882,6 @@ If you have multiple servers configured but you would like to disable some for a
905
882
  }
906
883
  ```
907
884
 
908
- #### Grouping MCP servers
909
-
910
- When you integrate multiple MCP servers to NBI, all of their tools will be available under the same chat participant `@mcp`. However, this may not be ideal in many situations. You may want to group certain servers and their tools based on their functionality. NBI lets you do that easily by configuring MCP chat participants. You can list the servers for each custom participant. If there are any unassigned MCP servers, then they will be used the default `@mcp` chat participant.
911
-
912
- Below is an example of creating a custom MCP participant. This configuration results in two chat participants `@mcp-fs` with `filesytem` MC server tools and `@mcp` with `servername1` and `servername1` MCP server tools.
913
-
914
- ```json
915
- {
916
- "chat_model": {
917
- ...
918
- },
919
- ...<other configuration>,
920
-
921
- "mcp": {
922
- "mcpServers": {
923
- "filesystem": {
924
- "command": "npx",
925
- "args": [
926
- "-y",
927
- "@modelcontextprotocol/server-filesystem",
928
- "/Users/mbektas/mcp-test"
929
- ]
930
- },
931
- "servername1": {
932
- "command": "",
933
- "args": [],
934
- },
935
- "servername2": {
936
- "command": "",
937
- "args": [],
938
- "disabled": true
939
- }
940
- },
941
- "participants": {
942
- "fs": {
943
- "name": "MCP - File system",
944
- "servers": ["filesystem"]
945
- }
946
- }
947
- }
948
- }
949
- ```
950
-
951
- #### Using NBI tools within MCP chat participants
952
-
953
- NBI allows you to access built-in tools from an MCP participant. You can do that by adding the list of built in NBI tools to your MCP participant configuration. The built-in tools available to MCP are `create_new_notebook`, `add_markdown_cell_to_notebook`, `add_code_cell_to_notebook`. Below is an example that integrates all these tools to MCP participant `@mcp-fs`.
954
-
955
- ```json
956
- "participants": {
957
- "fs": {
958
- "name": "MCP - File system",
959
- "servers": ["filesystem"],
960
- "nbiTools": [
961
- "create_new_notebook",
962
- "add_markdown_cell_to_notebook",
963
- "add_code_cell_to_notebook"
964
- ]
965
- }
966
- }
967
- ```
968
-
969
- This chat participant will allow you to run example prompts like below.
970
-
971
- ```
972
- @mcp-fs list the directories I have access to.
973
- ```
974
-
975
- ```
976
- @mcp-fs add a code cell which demonstrates ipywidgets Button to this notebook.
977
- ```
978
-
979
885
  ### Developer documentation
980
886
 
981
887
  For building locally and contributing see the [developer documentatation](CONTRIBUTING.md).
@@ -94,18 +94,18 @@ jupyter lab --NotebookIntelligence.notebook_execute_tool=env_enabled
94
94
 
95
95
  ### Configuration files
96
96
 
97
- NBI saves configuration at `~/.jupyter/nbi-config.json`. It also supports environment wide base configuration at `<env-prefix>/share/jupyter/nbi-config.json`. Organizations can ship default configuration at this environment wide config path. User's changes will be stored as overrides at `~/.jupyter/nbi-config.json`.
97
+ NBI saves configuration at `~/.jupyter/nbi/config.json`. It also supports environment wide base configuration at `<env-prefix>/share/jupyter/nbi/config.json`. Organizations can ship default configuration at this environment wide config path. User's changes will be stored as overrides at `~/.jupyter/nbi/config.json`.
98
98
 
99
99
  These config files are used for saving LLM provider, model and MCP configuration. Note that API keys you enter for your custom LLM providers will also be stored in these config files.
100
100
 
101
101
  > [!IMPORTANT]
102
- > Note that updating nbi-config.json manually requires restarting JupyterLab to take effect.
102
+ > Note that updating config.json manually requires restarting JupyterLab to take effect.
103
103
 
104
104
  ### Model Context Protocol ([MCP](https://modelcontextprotocol.io)) Support
105
105
 
106
106
  NBI seamlessly integrates with MCP servers. It supports servers with both Standard Input/Output (stdio) and Server-Sent Events (SSE) transports. The MCP support is limited to server tools at the moment.
107
107
 
108
- You can easily add MCP servers to NBI by editing the configuration file [nbi-config.json](#configuration-files). Simply add a key "mcp" and "mcpServers" under it as shown below.
108
+ You can easily add MCP servers to NBI by editing the configuration file [~/.jupyter/nbi/mcp.json](#configuration-files). Environment wide base configuration is also support using the file at `<env-prefix>/share/jupyter/nbi/mcp.json`.
109
109
 
110
110
  > [!NOTE]
111
111
  > Using MCP servers requires an LLM model with tool calling capabilities. All of the GitHub Copilot models provided in NBI support this feature. If you are using other providers make sure you choose a tool calling capable model.
@@ -113,47 +113,24 @@ You can easily add MCP servers to NBI by editing the configuration file [nbi-con
113
113
  > [!CAUTION]
114
114
  > Note that most MCP servers are run on the same computer as your JupyterLab installation and they can make irreversible changes to your computer and/or access private data. Make sure that you only install MCP servers from trusted sources.
115
115
 
116
+ ### MCP Config file example
117
+
116
118
  ```json
117
119
  {
118
- "chat_model": {
119
- ...
120
- },
121
- ...<other configuration>,
122
-
123
- "mcp": {
124
- "mcpServers": {
125
- "filesystem": {
126
- "command": "npx",
127
- "args": [
128
- "-y",
129
- "@modelcontextprotocol/server-filesystem",
130
- "/Users/mbektas/mcp-test"
131
- ]
132
- },
133
- }
120
+ "mcpServers": {
121
+ "filesystem": {
122
+ "command": "npx",
123
+ "args": [
124
+ "-y",
125
+ "@modelcontextprotocol/server-filesystem",
126
+ "/Users/mbektas/mcp-test"
127
+ ]
134
128
  }
129
+ }
135
130
  }
136
131
  ```
137
132
 
138
- This will automatically create a new chat participant in NBI and you can access it by starting your prompts with `@mcp`. Use `@mcp /info` prompt to get information on the tools provided by the MCP servers you configured. This chat participant will have access all the tools provided by the servers you configure.
139
-
140
- <img src="media/mcp-prompt.png" alt="Settings dialog" width=600 />
141
-
142
- By default, each tool call to MCP servers will require approval. If you would like to auto approve tools, you can do so by using the `"alwaysAllow": []` configuration key in the nbi-config.json. Simply list the names of tools.
143
-
144
- ```json
145
- "mcpServers": {
146
- "filesystem": {
147
- "command": "npx",
148
- "args": [
149
- "-y",
150
- "@modelcontextprotocol/server-filesystem",
151
- "/Users/mbektas/mcp-test"
152
- ],
153
- "alwaysAllow": ["list_allowed_directories", "list_directory"]
154
- },
155
- }
156
- ```
133
+ You can use Agent mode to access tools provided by MCP servers you configured.
157
134
 
158
135
  For servers with stdio transport, you can also set additional environment variables by using the `env` key. Environment variables are specified as key value pairs.
159
136
 
@@ -169,12 +146,12 @@ For servers with stdio transport, you can also set additional environment variab
169
146
  }
170
147
  ```
171
148
 
172
- Below is an example of a server configuration with SSE transport. For SSE transport servers, you can also specify headers to be sent as part of the requests.
149
+ Below is an example of a server configuration with Streamable HTTP transport. For Streamable HTTP transport servers, you can also specify headers to be sent as part of the requests.
173
150
 
174
151
  ```json
175
152
  "mcpServers": {
176
153
  "remoterservername": {
177
- "url": "http://127.0.0.1:8080/sse",
154
+ "url": "http://127.0.0.1:8080/mcp",
178
155
  "headers": {
179
156
  "Authorization": "Bearer mysecrettoken"
180
157
  }
@@ -198,77 +175,6 @@ If you have multiple servers configured but you would like to disable some for a
198
175
  }
199
176
  ```
200
177
 
201
- #### Grouping MCP servers
202
-
203
- When you integrate multiple MCP servers to NBI, all of their tools will be available under the same chat participant `@mcp`. However, this may not be ideal in many situations. You may want to group certain servers and their tools based on their functionality. NBI lets you do that easily by configuring MCP chat participants. You can list the servers for each custom participant. If there are any unassigned MCP servers, then they will be used the default `@mcp` chat participant.
204
-
205
- Below is an example of creating a custom MCP participant. This configuration results in two chat participants `@mcp-fs` with `filesytem` MC server tools and `@mcp` with `servername1` and `servername1` MCP server tools.
206
-
207
- ```json
208
- {
209
- "chat_model": {
210
- ...
211
- },
212
- ...<other configuration>,
213
-
214
- "mcp": {
215
- "mcpServers": {
216
- "filesystem": {
217
- "command": "npx",
218
- "args": [
219
- "-y",
220
- "@modelcontextprotocol/server-filesystem",
221
- "/Users/mbektas/mcp-test"
222
- ]
223
- },
224
- "servername1": {
225
- "command": "",
226
- "args": [],
227
- },
228
- "servername2": {
229
- "command": "",
230
- "args": [],
231
- "disabled": true
232
- }
233
- },
234
- "participants": {
235
- "fs": {
236
- "name": "MCP - File system",
237
- "servers": ["filesystem"]
238
- }
239
- }
240
- }
241
- }
242
- ```
243
-
244
- #### Using NBI tools within MCP chat participants
245
-
246
- NBI allows you to access built-in tools from an MCP participant. You can do that by adding the list of built in NBI tools to your MCP participant configuration. The built-in tools available to MCP are `create_new_notebook`, `add_markdown_cell_to_notebook`, `add_code_cell_to_notebook`. Below is an example that integrates all these tools to MCP participant `@mcp-fs`.
247
-
248
- ```json
249
- "participants": {
250
- "fs": {
251
- "name": "MCP - File system",
252
- "servers": ["filesystem"],
253
- "nbiTools": [
254
- "create_new_notebook",
255
- "add_markdown_cell_to_notebook",
256
- "add_code_cell_to_notebook"
257
- ]
258
- }
259
- }
260
- ```
261
-
262
- This chat participant will allow you to run example prompts like below.
263
-
264
- ```
265
- @mcp-fs list the directories I have access to.
266
- ```
267
-
268
- ```
269
- @mcp-fs add a code cell which demonstrates ipywidgets Button to this notebook.
270
- ```
271
-
272
178
  ### Developer documentation
273
179
 
274
180
  For building locally and contributing see the [developer documentatation](CONTRIBUTING.md).
@@ -1,4 +1,4 @@
1
1
  # This file is auto-generated by Hatchling. As such, do not:
2
2
  # - modify
3
3
  # - track in version control e.g. be sure to add to .gitignore
4
- __version__ = VERSION = '2.4.2'
4
+ __version__ = VERSION = '2.5.0'
@@ -16,6 +16,7 @@ from notebook_intelligence.llm_providers.litellm_compatible_llm_provider import
16
16
  from notebook_intelligence.llm_providers.ollama_llm_provider import OllamaLLMProvider
17
17
  from notebook_intelligence.llm_providers.openai_compatible_llm_provider import OpenAICompatibleLLMProvider
18
18
  from notebook_intelligence.mcp_manager import MCPManager
19
+ from notebook_intelligence.util import ThreadSafeWebSocketConnector
19
20
 
20
21
  log = logging.getLogger(__name__)
21
22
 
@@ -40,6 +41,7 @@ class AIServiceManager(Host):
40
41
  self._litellm_compatible_llm_provider = LiteLLMCompatibleLLMProvider()
41
42
  self._ollama_llm_provider = OllamaLLMProvider()
42
43
  self._extensions = []
44
+ self._websocket_connector: ThreadSafeWebSocketConnector = None
43
45
  self.initialize()
44
46
 
45
47
  @property
@@ -50,6 +52,15 @@ class AIServiceManager(Host):
50
52
  def ollama_llm_provider(self) -> OllamaLLMProvider:
51
53
  return self._ollama_llm_provider
52
54
 
55
+ @property
56
+ def websocket_connector(self) -> ThreadSafeWebSocketConnector:
57
+ return self._websocket_connector
58
+
59
+ @websocket_connector.setter
60
+ def websocket_connector(self, _websocket_connector: ThreadSafeWebSocketConnector):
61
+ self._websocket_connector = _websocket_connector
62
+ self._mcp_manager.websocket_connector = _websocket_connector
63
+
53
64
  def initialize(self):
54
65
  self.chat_participants = {}
55
66
  self.register_llm_provider(GitHubCopilotLLMProvider())
@@ -370,3 +381,15 @@ class AIServiceManager(Host):
370
381
  if extension.id == extension_id:
371
382
  return extension
372
383
  return None
384
+
385
+ def handle_stop_request(self):
386
+ self._mcp_manager.handle_stop_request()
387
+
388
+ def update_mcp_server_connections(self, disabled_mcp_servers: list[str]):
389
+ self._mcp_manager.update_mcp_server_connections(disabled_mcp_servers)
390
+
391
+ def connect_mcp_server(self, server_name: str):
392
+ self._mcp_manager.connect_mcp_server(server_name)
393
+
394
+ def disconnect_mcp_server(self, server_name: str):
395
+ self._mcp_manager.disconnect_mcp_server(server_name)
@@ -1,7 +1,6 @@
1
1
  # Copyright (c) Mehmet Bektas <mbektasgh@outlook.com>
2
2
 
3
3
  import asyncio
4
- import json
5
4
  from typing import Any, Callable, Dict, Union
6
5
  from dataclasses import asdict, dataclass
7
6
  from enum import Enum
@@ -29,6 +28,7 @@ class BackendMessageType(str, Enum):
29
28
  StreamEnd = 'stream-end'
30
29
  RunUICommand = 'run-ui-command'
31
30
  GitHubCopilotLoginStatusChange = 'github-copilot-login-status-change'
31
+ MCPServerStatusChange = 'mcp-server-status-change'
32
32
 
33
33
  class ResponseStreamDataType(str, Enum):
34
34
  LLMRaw = 'llm-raw'
@@ -49,6 +49,15 @@ class BuiltinToolset(str, Enum):
49
49
  NotebookExecute = 'nbi-notebook-execute'
50
50
  PythonFileEdit = 'nbi-python-file-edit'
51
51
 
52
+ class MCPServerStatus(str, Enum):
53
+ NotConnected = 'not-connected'
54
+ Connecting = 'connecting'
55
+ Disconnecting = 'disconnecting'
56
+ FailedToConnect = 'failed-to-connect'
57
+ Connected = 'connected'
58
+ UpdatingToolList = 'updating-tool-list'
59
+ UpdatedToolList = 'updated-tool-list'
60
+
52
61
  class Signal:
53
62
  def __init__(self):
54
63
  self._listeners = []
@@ -376,14 +385,18 @@ class MCPServer:
376
385
  @property
377
386
  def name(self) -> str:
378
387
  return NotImplemented
388
+
389
+ @property
390
+ def status(self) -> MCPServerStatus:
391
+ return NotImplemented
379
392
 
380
- async def connect(self):
393
+ def connect(self):
381
394
  return NotImplemented
382
395
 
383
- async def disconnect(self):
396
+ def disconnect(self):
384
397
  return NotImplemented
385
398
 
386
- async def update_tool_list(self):
399
+ def update_tool_list(self):
387
400
  return NotImplemented
388
401
 
389
402
  def get_tools(self) -> list[Tool]:
@@ -392,7 +405,7 @@ class MCPServer:
392
405
  def get_tool(self, tool_name: str) -> Tool:
393
406
  return NotImplemented
394
407
 
395
- async def call_tool(self, tool_name: str, tool_args: dict):
408
+ def call_tool(self, tool_name: str, tool_args: dict):
396
409
  return NotImplemented
397
410
 
398
411
  def auto_approve(tool: SimpleTool):
@@ -120,3 +120,22 @@ class NBIConfig:
120
120
  def using_github_copilot_service(self) -> bool:
121
121
  return self.chat_model.get("provider") == 'github-copilot' or \
122
122
  self.inline_completion_model.get("provider") == 'github-copilot'
123
+
124
+ @property
125
+ def mcp_server_settings(self):
126
+ return self.get('mcp_server_settings', {})
127
+
128
+ @property
129
+ def rules_enabled(self) -> bool:
130
+ """Check if the ruleset system is enabled."""
131
+ return self.get('rules_enabled', True)
132
+
133
+ @property
134
+ def rules_directory(self) -> str:
135
+ """Get the rules directory path."""
136
+ return os.path.join(self.nbi_user_dir, 'rules')
137
+
138
+ @property
139
+ def active_rules(self) -> dict:
140
+ """Get dictionary of active rule states (filename -> bool)."""
141
+ return self.get('active_rules', {})
@@ -27,6 +27,7 @@ from notebook_intelligence.util import ThreadSafeWebSocketConnector
27
27
  ai_service_manager: AIServiceManager = None
28
28
  log = logging.getLogger(__name__)
29
29
  tiktoken_encoding = tiktoken.encoding_for_model('gpt-4o')
30
+ thread_safe_websocket_connector: ThreadSafeWebSocketConnector = None
30
31
 
31
32
  class GetCapabilitiesHandler(APIHandler):
32
33
  notebook_execute_tool = 'enabled'
@@ -39,8 +40,7 @@ class GetCapabilitiesHandler(APIHandler):
39
40
  notebook_execute_tool_enabled = self.notebook_execute_tool == 'enabled' or (self.notebook_execute_tool == 'env_enabled' and os.getenv('NBI_NOTEBOOK_EXECUTE_TOOL', 'disabled') == 'enabled')
40
41
  allowed_builtin_toolsets = [{"id": toolset.id, "name": toolset.name} for toolset in built_in_toolsets.values() if toolset.id != BuiltinToolset.NotebookExecute or notebook_execute_tool_enabled]
41
42
  mcp_servers = ai_service_manager.get_mcp_servers()
42
- mcp_server_tools = [{"id": mcp_server.name, "tools": [{"name": tool.name, "description": tool.description} for tool in mcp_server.get_tools()]} for mcp_server in mcp_servers]
43
- mcp_server_tools = [tool for tool in mcp_server_tools if len(tool["tools"]) > 0]
43
+ mcp_server_tools = [{"id": mcp_server.name, "status": mcp_server.status, "tools": [{"name": tool.name, "description": tool.description} for tool in mcp_server.get_tools()]} for mcp_server in mcp_servers]
44
44
  # sort by server id
45
45
  mcp_server_tools.sort(key=lambda server: server["id"])
46
46
 
@@ -88,6 +88,7 @@ class GetCapabilitiesHandler(APIHandler):
88
88
  "mcpServers": mcp_server_tools,
89
89
  "extensions": extensions
90
90
  },
91
+ "mcp_server_settings": nbi_config.mcp_server_settings,
91
92
  "default_chat_mode": nbi_config.default_chat_mode
92
93
  }
93
94
  for participant_id in ai_service_manager.chat_participants:
@@ -105,7 +106,8 @@ class ConfigHandler(APIHandler):
105
106
  @tornado.web.authenticated
106
107
  def post(self):
107
108
  data = json.loads(self.request.body)
108
- valid_keys = set(["default_chat_mode", "chat_model", "inline_completion_model", "store_github_access_token"])
109
+ valid_keys = set(["default_chat_mode", "chat_model", "inline_completion_model", "store_github_access_token", "mcp_server_settings"])
110
+ has_model_change = "chat_model" in data or "inline_completion_model" in data
109
111
  for key in data:
110
112
  if key in valid_keys:
111
113
  ai_service_manager.nbi_config.set(key, data[key])
@@ -114,8 +116,17 @@ class ConfigHandler(APIHandler):
114
116
  github_copilot.store_github_access_token()
115
117
  else:
116
118
  github_copilot.delete_stored_github_access_token()
119
+ elif key == "mcp_server_settings":
120
+ disabled_mcp_servers = []
121
+ for server_id in data[key]:
122
+ server_settings = data[key][server_id]
123
+ if server_settings.get("disabled") == True:
124
+ disabled_mcp_servers.append(server_id)
125
+ ai_service_manager.update_mcp_server_connections(disabled_mcp_servers)
126
+
117
127
  ai_service_manager.nbi_config.save()
118
- ai_service_manager.update_models_from_config()
128
+ if has_model_change:
129
+ ai_service_manager.update_models_from_config()
119
130
  self.finish(json.dumps({}))
120
131
 
121
132
  class UpdateProviderModelsHandler(APIHandler):
@@ -126,18 +137,10 @@ class UpdateProviderModelsHandler(APIHandler):
126
137
  ai_service_manager.ollama_llm_provider.update_chat_model_list()
127
138
  self.finish(json.dumps({}))
128
139
 
129
- class ReloadMCPServersHandler(APIHandler):
130
- @tornado.web.authenticated
131
- def post(self):
132
- ai_service_manager.nbi_config.load()
133
- ai_service_manager.update_mcp_servers()
134
- self.finish(json.dumps({
135
- "mcpServers": [{"id": server.name} for server in ai_service_manager.get_mcp_servers()]
136
- }))
137
-
138
140
  class MCPConfigFileHandler(APIHandler):
139
141
  @tornado.web.authenticated
140
142
  def get(self):
143
+ ai_service_manager.nbi_config.load()
141
144
  mcp_config = ai_service_manager.nbi_config.mcp.copy()
142
145
  if "mcpServers" not in mcp_config:
143
146
  mcp_config["mcpServers"] = {}
@@ -156,6 +159,15 @@ class MCPConfigFileHandler(APIHandler):
156
159
  self.finish(json.dumps({"status": "error", "message": str(e)}))
157
160
  return
158
161
 
162
+ class ReloadMCPServersHandler(APIHandler):
163
+ @tornado.web.authenticated
164
+ def post(self):
165
+ ai_service_manager.nbi_config.load()
166
+ ai_service_manager.update_mcp_servers()
167
+ self.finish(json.dumps({
168
+ "mcpServers": [{"id": server.name} for server in ai_service_manager.get_mcp_servers()]
169
+ }))
170
+
159
171
  class EmitTelemetryEventHandler(APIHandler):
160
172
  @tornado.web.authenticated
161
173
  def post(self):
@@ -453,7 +465,9 @@ class WebsocketCopilotHandler(websocket.WebSocketHandler):
453
465
  # TODO: cleanup
454
466
  self._messageCallbackHandlers: dict[str, MessageCallbackHandlers] = {}
455
467
  self.chat_history = ChatHistory()
456
- github_copilot.websocket_connector = ThreadSafeWebSocketConnector(self)
468
+ ws_connector = ThreadSafeWebSocketConnector(self)
469
+ ai_service_manager.websocket_connector = ws_connector
470
+ github_copilot.websocket_connector = ws_connector
457
471
 
458
472
  def open(self):
459
473
  pass
@@ -631,6 +645,7 @@ class NotebookIntelligence(ExtensionApp):
631
645
  async def stop_extension(self):
632
646
  log.info(f"Stopping {self.name} extension...")
633
647
  github_copilot.handle_stop_request()
648
+ ai_service_manager.handle_stop_request()
634
649
 
635
650
  def _setup_handlers(self, web_app):
636
651
  host_pattern = ".*$"
@@ -639,8 +654,8 @@ class NotebookIntelligence(ExtensionApp):
639
654
  route_pattern_capabilities = url_path_join(base_url, "notebook-intelligence", "capabilities")
640
655
  route_pattern_config = url_path_join(base_url, "notebook-intelligence", "config")
641
656
  route_pattern_update_provider_models = url_path_join(base_url, "notebook-intelligence", "update-provider-models")
642
- route_pattern_reload_mcp_servers = url_path_join(base_url, "notebook-intelligence", "reload-mcp-servers")
643
657
  route_pattern_mcp_config_file = url_path_join(base_url, "notebook-intelligence", "mcp-config-file")
658
+ route_pattern_reload_mcp_servers = url_path_join(base_url, "notebook-intelligence", "reload-mcp-servers")
644
659
  route_pattern_emit_telemetry_event = url_path_join(base_url, "notebook-intelligence", "emit-telemetry-event")
645
660
  route_pattern_github_login_status = url_path_join(base_url, "notebook-intelligence", "gh-login-status")
646
661
  route_pattern_github_login = url_path_join(base_url, "notebook-intelligence", "gh-login")
@@ -651,8 +666,8 @@ class NotebookIntelligence(ExtensionApp):
651
666
  (route_pattern_capabilities, GetCapabilitiesHandler),
652
667
  (route_pattern_config, ConfigHandler),
653
668
  (route_pattern_update_provider_models, UpdateProviderModelsHandler),
654
- (route_pattern_reload_mcp_servers, ReloadMCPServersHandler),
655
669
  (route_pattern_mcp_config_file, MCPConfigFileHandler),
670
+ (route_pattern_reload_mcp_servers, ReloadMCPServersHandler),
656
671
  (route_pattern_emit_telemetry_event, EmitTelemetryEventHandler),
657
672
  (route_pattern_github_login_status, GetGitHubLoginStatusHandler),
658
673
  (route_pattern_github_login, PostGitHubLoginHandler),
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@notebook-intelligence/notebook-intelligence",
3
- "version": "2.4.2",
3
+ "version": "2.5.0",
4
4
  "description": "AI coding assistant for JupyterLab",
5
5
  "keywords": [
6
6
  "AI",
@@ -130,7 +130,7 @@
130
130
  }
131
131
  },
132
132
  "_build": {
133
- "load": "static/remoteEntry.d9d709f6862dfa2e5a69.js",
133
+ "load": "static/remoteEntry.84c6d4df1ff766bc53bf.js",
134
134
  "extension": "./extension",
135
135
  "style": "./style"
136
136
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@notebook-intelligence/notebook-intelligence",
3
- "version": "2.4.2",
3
+ "version": "2.5.0",
4
4
  "description": "AI coding assistant for JupyterLab",
5
5
  "keywords": [
6
6
  "AI",