@rekog/mcp-nest 1.1.4 → 1.2.0

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 (36) hide show
  1. package/.rinorism/index.d.ts +1 -0
  2. package/.vscode/settings.json +1 -0
  3. package/README.md +157 -15
  4. package/coverage/clover.xml +135 -121
  5. package/coverage/coverage-final.json +8 -8
  6. package/coverage/lcov-report/index.html +39 -39
  7. package/coverage/lcov.info +208 -207
  8. package/dist/controllers/sse.controller.factory.d.ts +13 -5
  9. package/dist/controllers/sse.controller.factory.d.ts.map +1 -1
  10. package/dist/controllers/sse.controller.factory.js +19 -6
  11. package/dist/controllers/sse.controller.factory.js.map +1 -1
  12. package/dist/index.d.ts +2 -0
  13. package/dist/index.d.ts.map +1 -1
  14. package/dist/index.js +2 -0
  15. package/dist/index.js.map +1 -1
  16. package/dist/interfaces/mcp-options.interface.d.ts +2 -0
  17. package/dist/interfaces/mcp-options.interface.d.ts.map +1 -1
  18. package/dist/mcp.module.d.ts.map +1 -1
  19. package/dist/mcp.module.js +10 -6
  20. package/dist/mcp.module.js.map +1 -1
  21. package/dist/services/mcp-tool-registry.service.d.ts +19 -0
  22. package/dist/services/mcp-tool-registry.service.d.ts.map +1 -0
  23. package/dist/services/mcp-tool-registry.service.js +66 -0
  24. package/dist/services/mcp-tool-registry.service.js.map +1 -0
  25. package/dist/services/mcp-tools-executor.service.d.ts +84 -0
  26. package/dist/services/mcp-tools-executor.service.d.ts.map +1 -0
  27. package/dist/services/mcp-tools-executor.service.js +154 -0
  28. package/dist/services/mcp-tools-executor.service.js.map +1 -0
  29. package/dist/services/mcp-tools.discovery.d.ts +19 -15
  30. package/dist/services/mcp-tools.discovery.d.ts.map +1 -1
  31. package/dist/services/mcp-tools.discovery.js +66 -127
  32. package/dist/services/mcp-tools.discovery.js.map +1 -1
  33. package/package.json +1 -1
  34. package/tests/mcp-auth.e2e.spec.ts +231 -0
  35. package/tests/mcp.e2e.spec.ts +30 -73
  36. package/tsconfig.tsbuildinfo +1 -1
@@ -0,0 +1 @@
1
+ export * from './dist';
@@ -0,0 +1 @@
1
+ {}
package/README.md CHANGED
@@ -8,11 +8,12 @@ A NestJS module for exposing your services as an MCP (Model Context Protocol) se
8
8
  - **Tool Discovery**: Automatically discover and register tools using decorators
9
9
  - **Tool Request Validation**: Define Zod schemas to validate tool requests.
10
10
  - **Progress Notifications**: Send continuous progress updates from tools to clients.
11
+ - **Authentication**: Integrates with NestJS Guards for securing endpoints.
11
12
 
12
13
  ## Installation
13
14
 
14
15
  ```bash
15
- npm install @rekog/mcp-nest reflect-metadata @modelcontextprotocol/sdk zod
16
+ npm install @rekog/mcp-nest reflect-metadata @modelcontextprotocol/sdk zod @nestjs/common @nestjs/core
16
17
  ```
17
18
 
18
19
  ## Quick Start
@@ -42,9 +43,8 @@ export class AppModule {}
42
43
  ```typescript
43
44
  // greeting.tool.ts
44
45
  import { Injectable } from '@nestjs/common';
45
- import { Tool } from '@rekog/mcp-nest';
46
+ import { Tool, Context } from '@rekog/mcp-nest';
46
47
  import { z } from 'zod';
47
- import { Context } from '@rekog/mcp-nest/dist/services/mcp-tools.discovery';
48
48
  import { Progress } from '@modelcontextprotocol/sdk/types';
49
49
 
50
50
  @Injectable()
@@ -82,12 +82,111 @@ export class GreetingTool {
82
82
 
83
83
  You are done!
84
84
 
85
+ ## Authentication
86
+
87
+ You can secure your MCP endpoints using standard NestJS Guards.
88
+
89
+ ### 1. Create a Guard
90
+
91
+ Implement the `CanActivate` interface. The guard should handle request validation (e.g., checking JWTs, API keys) and optionally attach user information to the request object.
92
+ <details>
93
+ <summary>Example Guard Implementation</summary>
94
+
95
+ ```typescript
96
+ // auth.guard.ts
97
+ import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';
98
+ import { Observable } from 'rxjs';
99
+
100
+ @Injectable()
101
+ export class AuthGuard implements CanActivate {
102
+ canActivate(
103
+ context: ExecutionContext,
104
+ ): boolean | Promise<boolean> | Observable<boolean> {
105
+ const request = context.switchToHttp().getRequest();
106
+ const authorization = request.headers.authorization;
107
+
108
+ // Example: Check for a specific Bearer token
109
+ if (authorization && authorization.startsWith('Bearer ')) {
110
+ const token = authorization.substring(7);
111
+ if (token === 'your-secret-token') {
112
+ // Attach user info if needed (optional)
113
+ request.user = { id: 'user-123', roles: ['admin'] };
114
+ return true; // Allow access
115
+ }
116
+ }
117
+
118
+ return false; // Deny access
119
+ }
120
+ }
121
+ ```
122
+
123
+ </details>
124
+
125
+ ### 2. Apply the Guard
126
+
127
+ Pass your guard(s) to the `McpModule.forRoot` configuration. The guard(s) will be applied to both the `/sse` and `/messages` endpoints.
128
+
129
+ ```typescript
130
+ // app.module.ts
131
+ import { Module } from '@nestjs/common';
132
+ import { McpModule } from '@rekog/mcp-nest';
133
+ import { GreetingTool } from './greeting.tool';
134
+ import { AuthGuard } from './auth.guard';
135
+
136
+ @Module({
137
+ imports: [
138
+ McpModule.forRoot({
139
+ name: 'my-mcp-server',
140
+ version: '1.0.0',
141
+ guards: [AuthGuard] // Apply the guard here
142
+ })
143
+ ],
144
+ providers: [GreetingTool, AuthGuard] // Ensure the Guard is also provided
145
+ })
146
+ export class AppModule {}
147
+ ```
148
+
149
+ ### 3. Access User Context in Tools (Optional)
150
+
151
+ If your guard attaches user information to the `request` object (e.g., `request.user = ...`), you can access it in your tool as the third parameter.
152
+
153
+ ```typescript
154
+ // authenticated-greeting.tool.ts
155
+ import { Injectable } from '@nestjs/common';
156
+ import { Tool, Context } from '@rekog/mcp-nest';
157
+ import { z } from 'zod';
158
+ import { Request } from 'express'; // Import Request from express
159
+
160
+ @Injectable()
161
+ export class AuthenticatedGreetingTool {
162
+
163
+ @Tool({
164
+ name: 'auth-hello-world',
165
+ description: 'Greets the authenticated user',
166
+ parameters: z.object({}), // No parameters needed for this example
167
+ })
168
+ // Add 'request' as the third parameter
169
+ async sayAuthHello(args: {}, context: Context, request: Request & { user?: { id: string } }) {
170
+ const userId = request.user?.id || 'Anonymous';
171
+ const greeting = `Hello, user ${userId}!`;
172
+
173
+ return {
174
+ content: [{ type: 'text', text: greeting }],
175
+ };
176
+ }
177
+ }
178
+ ```
179
+
180
+ *Note: Ensure your tool (`AuthenticatedGreetingTool` in this example) is added to the `providers` array in your `AppModule`.*
181
+
85
182
  ## Client Connection
86
183
 
87
- Clients can connect using the MCP SDK:
184
+ Clients need to provide the necessary credentials (e.g., Authorization header) when connecting if authentication is enabled.
185
+
186
+ ### Unauthenticated Client
88
187
 
89
188
  ```typescript
90
- // client.ts
189
+ // client.ts (no authentication)
91
190
  import { Client } from '@modelcontextprotocol/sdk/client';
92
191
  import { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse';
93
192
 
@@ -100,17 +199,47 @@ await client.connect(
100
199
  new SSEClientTransport(new URL('http://localhost:3000/sse'))
101
200
  );
102
201
 
103
- // Execute the 'hello-world' tool with progress tracking
202
+ // ... list tools, call tools etc.
203
+ ```
204
+
205
+ ### Authenticated Client
206
+
207
+ Pass request options (like headers) to the `SSEClientTransport`.
208
+
209
+ ```typescript
210
+ // client.ts (with authentication)
211
+ import { Client } from '@modelcontextprotocol/sdk/client';
212
+ import { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse';
213
+
214
+ const client = new Client(
215
+ { name: 'client-name', version: '1.0.0' },
216
+ { capabilities: {} }
217
+ );
218
+
219
+ const transport = new SSEClientTransport(
220
+ new URL('http://localhost:3000/sse'),
221
+ {
222
+ // Provide necessary credentials here
223
+ requestInit: {
224
+ headers: {
225
+ Authorization: 'Bearer your-secret-token' // Match guard expectation
226
+ }
227
+ }
228
+ }
229
+ );
230
+
231
+ await client.connect(transport);
232
+
233
+
234
+ // Execute the 'auth-hello-world' tool
104
235
  const greetResult = await client.callTool(
105
236
  {
106
- name: 'hello-world',
107
- arguments: {
108
- name: 'MCP User',
109
- },
237
+ name: 'auth-hello-world',
238
+ arguments: {},
110
239
  },
111
- undefined, // responseSchema is optional, or you can define a Zod schema here
240
+ undefined, // responseSchema is optional
112
241
  {
113
- onprogress: (progress) => {
242
+ onprogress: (progress) => { // Example progress handler
114
243
  console.log(
115
244
  `Progress: ${progress.progress}/${progress.total}`
116
245
  );
@@ -118,13 +247,13 @@ const greetResult = await client.callTool(
118
247
  },
119
248
  );
120
249
 
121
- console.log(greetResult.content[0].text); // Output: Hello MCP User! I'm Test User from Test Org.
250
+ console.log(greetResult.content[0].text); // Output: Hello, user user-123!
122
251
  ```
123
252
 
124
253
  ## API Endpoints
125
254
 
126
- - `GET /sse`: SSE connection endpoint
127
- - `POST /messages`: Tool execution endpoint
255
+ - `GET /sse`: SSE connection endpoint (Protected by guards if configured)
256
+ - `POST /messages`: Tool execution endpoint (Protected by guards if configured)
128
257
 
129
258
  ## Configuration Reference
130
259
 
@@ -135,6 +264,7 @@ console.log(greetResult.content[0].text); // Output: Hello MCP User! I'm Test Us
135
264
  | `name` | string | Server name | - |
136
265
  | `version` | string | Server version | - |
137
266
  | `capabilities` | Record<string, any> | Server capabilities, defines what the server can do. | `{}` |
267
+ | `guards` | `any[]` (NestJS Guards) | An array of NestJS Guards to apply to the MCP endpoints. | `[]` |
138
268
  | `sseEndpoint` | string (optional) | Endpoint for SSE connections. | `'sse'` |
139
269
  | `messagesEndpoint` | string (optional) | Endpoint for handling tool execution. | `'messages'` |
140
270
  | `globalApiPrefix` | string (optional) | Global API prefix for all endpoints. | `''` |
@@ -150,3 +280,15 @@ The `@Tool` decorator is used to define a method as an MCP tool.
150
280
  - `name`: The name of the tool. This will be used to list it in the `listTools` request.
151
281
  - `description`: A description of the tool.
152
282
  - `parameters`: (Optional) A Zod schema defining the expected structure of the tool's input arguments.
283
+
284
+ ### Context Parameter
285
+
286
+ The second parameter passed to a `@Tool` decorated method is the `Context` object.
287
+
288
+ - `context.reportProgress(progress: Progress)`: Sends a progress update message to the client. `Progress` typically has `{ progress: number, total: number }`.
289
+
290
+ ### Request Paramter
291
+
292
+ The third parameter passed to a `@Tool` decorated method is the `Request` object.
293
+
294
+ - `request`: The request object from the underlying HTTP framework (e.g., Express). This can be used to access headers, query parameters, etc.
@@ -1,92 +1,78 @@
1
1
  <?xml version="1.0" encoding="UTF-8"?>
2
- <coverage generated="1742497116281" clover="3.2.0">
3
- <project timestamp="1742497116281" name="All files">
4
- <metrics statements="130" coveredstatements="98" conditionals="45" coveredconditionals="21" methods="32" coveredmethods="21" elements="207" coveredelements="140" complexity="0" loc="130" ncloc="130" packages="5" files="8" classes="8"/>
2
+ <coverage generated="1743581275515" clover="3.2.0">
3
+ <project timestamp="1743581275515" name="All files">
4
+ <metrics statements="144" coveredstatements="72" conditionals="42" coveredconditionals="11" methods="27" coveredmethods="9" elements="213" coveredelements="92" complexity="0" loc="144" ncloc="144" packages="5" files="8" classes="8"/>
5
5
  <package name="src">
6
- <metrics statements="32" coveredstatements="16" conditionals="22" coveredconditionals="7" methods="7" coveredmethods="2"/>
7
- <file name="index.ts" path="/home/rinor/explore/MCP-Nest/src/index.ts">
6
+ <metrics statements="17" coveredstatements="17" conditionals="10" coveredconditionals="8" methods="2" coveredmethods="2"/>
7
+ <file name="index.ts" path="/home/rinor/explore/nest-mcp/src/index.ts">
8
8
  <metrics statements="3" coveredstatements="3" conditionals="0" coveredconditionals="0" methods="0" coveredmethods="0"/>
9
9
  <line num="1" count="1" type="stmt"/>
10
10
  <line num="2" count="1" type="stmt"/>
11
11
  <line num="3" count="1" type="stmt"/>
12
12
  </file>
13
- <file name="mcp.module.ts" path="/home/rinor/explore/MCP-Nest/src/mcp.module.ts">
14
- <metrics statements="29" coveredstatements="13" conditionals="22" coveredconditionals="7" methods="7" coveredmethods="2"/>
13
+ <file name="mcp.module.ts" path="/home/rinor/explore/nest-mcp/src/mcp.module.ts">
14
+ <metrics statements="14" coveredstatements="14" conditionals="10" coveredconditionals="8" methods="2" coveredmethods="2"/>
15
15
  <line num="1" count="1" type="stmt"/>
16
- <line num="2" count="1" type="stmt"/>
17
- <line num="3" count="1" type="stmt"/>
18
16
  <line num="6" count="1" type="stmt"/>
19
- <line num="7" count="1" type="stmt"/>
20
- <line num="10" count="1" type="stmt"/>
21
- <line num="12" count="1" type="cond" truecount="2" falsecount="0"/>
22
- <line num="13" count="1" type="cond" truecount="2" falsecount="0"/>
23
- <line num="14" count="1" type="cond" truecount="2" falsecount="0"/>
17
+ <line num="11" count="1" type="stmt"/>
18
+ <line num="12" count="1" type="stmt"/>
19
+ <line num="13" count="1" type="stmt"/>
24
20
  <line num="16" count="1" type="stmt"/>
25
- <line num="18" count="1" type="stmt"/>
26
- <line num="30" count="1" type="stmt"/>
27
- <line num="34" count="1" type="stmt"/>
28
- <line num="45" count="0" type="stmt"/>
29
- <line num="47" count="0" type="stmt"/>
30
- <line num="56" count="0" type="stmt"/>
31
- <line num="60" count="0" type="stmt"/>
32
- <line num="71" count="0" type="cond" truecount="0" falsecount="3"/>
33
- <line num="72" count="0" type="stmt"/>
34
- <line num="75" count="0" type="cond" truecount="0" falsecount="1"/>
35
- <line num="76" count="0" type="stmt"/>
36
- <line num="79" count="0" type="stmt"/>
37
- <line num="89" count="0" type="cond" truecount="0" falsecount="1"/>
38
- <line num="90" count="0" type="stmt"/>
39
- <line num="97" count="0" type="cond" truecount="0" falsecount="2"/>
40
- <line num="98" count="0" type="cond" truecount="0" falsecount="1"/>
41
- <line num="99" count="0" type="stmt"/>
42
- <line num="102" count="0" type="stmt"/>
43
- <line num="105" count="0" type="stmt"/>
21
+ <line num="18" count="1" type="cond" truecount="2" falsecount="0"/>
22
+ <line num="19" count="1" type="cond" truecount="2" falsecount="0"/>
23
+ <line num="20" count="1" type="cond" truecount="2" falsecount="0"/>
24
+ <line num="21" count="1" type="cond" truecount="1" falsecount="1"/>
25
+ <line num="24" count="1" type="stmt"/>
26
+ <line num="31" count="1" type="stmt"/>
27
+ <line num="48" count="1" type="stmt"/>
28
+ <line num="52" count="1" type="stmt"/>
44
29
  </file>
45
30
  </package>
46
31
  <package name="src.controllers">
47
- <metrics statements="26" coveredstatements="24" conditionals="3" coveredconditionals="1" methods="5" coveredmethods="4"/>
48
- <file name="sse.controller.factory.ts" path="/home/rinor/explore/MCP-Nest/src/controllers/sse.controller.factory.ts">
49
- <metrics statements="26" coveredstatements="24" conditionals="3" coveredconditionals="1" methods="5" coveredmethods="4"/>
32
+ <metrics statements="27" coveredstatements="24" conditionals="4" coveredconditionals="2" methods="5" coveredmethods="4"/>
33
+ <file name="sse.controller.factory.ts" path="/home/rinor/explore/nest-mcp/src/controllers/sse.controller.factory.ts">
34
+ <metrics statements="27" coveredstatements="24" conditionals="4" coveredconditionals="2" methods="5" coveredmethods="4"/>
50
35
  <line num="1" count="1" type="stmt"/>
51
- <line num="4" count="1" type="stmt"/>
52
- <line num="5" count="1" type="stmt"/>
53
- <line num="7" count="1" type="stmt"/>
54
- <line num="10" count="1" type="stmt"/>
55
36
  <line num="15" count="1" type="stmt"/>
56
37
  <line num="16" count="1" type="stmt"/>
57
- <line num="17" count="1" type="stmt"/>
38
+ <line num="18" count="1" type="stmt"/>
58
39
  <line num="20" count="1" type="stmt"/>
59
- <line num="21" count="1" type="stmt"/>
60
- <line num="25" count="1" type="stmt"/>
61
- <line num="26" count="2" type="stmt"/>
62
- <line num="27" count="2" type="stmt"/>
63
- <line num="29" count="2" type="stmt"/>
64
- <line num="35" count="2" type="stmt"/>
40
+ <line num="26" count="1" type="stmt"/>
41
+ <line num="27" count="1" type="stmt"/>
42
+ <line num="28" count="4" type="stmt"/>
43
+ <line num="31" count="4" type="stmt"/>
44
+ <line num="32" count="4" type="stmt"/>
45
+ <line num="36" count="1" type="stmt"/>
65
46
  <line num="37" count="2" type="stmt"/>
66
- <line num="39" count="2" type="stmt"/>
67
- <line num="40" count="0" type="stmt"/>
47
+ <line num="41" count="2" type="stmt"/>
68
48
  <line num="43" count="2" type="stmt"/>
69
- <line num="47" count="1" type="stmt"/>
70
- <line num="48" count="7" type="stmt"/>
71
- <line num="50" count="7" type="stmt"/>
72
- <line num="52" count="7" type="cond" truecount="0" falsecount="1"/>
73
- <line num="53" count="0" type="stmt"/>
74
- <line num="55" count="7" type="stmt"/>
75
- <line num="59" count="1" type="stmt"/>
49
+ <line num="51" count="2" type="stmt"/>
50
+ <line num="53" count="2" type="stmt"/>
51
+ <line num="55" count="2" type="stmt"/>
52
+ <line num="56" count="0" type="stmt"/>
53
+ <line num="57" count="0" type="stmt"/>
54
+ <line num="60" count="2" type="stmt"/>
55
+ <line num="65" count="1" type="stmt"/>
56
+ <line num="70" count="2" type="stmt"/>
57
+ <line num="71" count="2" type="stmt"/>
58
+ <line num="73" count="2" type="cond" truecount="1" falsecount="0"/>
59
+ <line num="74" count="2" type="stmt"/>
60
+ <line num="77" count="0" type="stmt"/>
61
+ <line num="81" count="1" type="stmt"/>
76
62
  </file>
77
63
  </package>
78
64
  <package name="src.decorators">
79
65
  <metrics statements="7" coveredstatements="7" conditionals="0" coveredconditionals="0" methods="1" coveredmethods="1"/>
80
- <file name="constants.ts" path="/home/rinor/explore/MCP-Nest/src/decorators/constants.ts">
66
+ <file name="constants.ts" path="/home/rinor/explore/nest-mcp/src/decorators/constants.ts">
81
67
  <metrics statements="1" coveredstatements="1" conditionals="0" coveredconditionals="0" methods="0" coveredmethods="0"/>
82
68
  <line num="1" count="1" type="stmt"/>
83
69
  </file>
84
- <file name="index.ts" path="/home/rinor/explore/MCP-Nest/src/decorators/index.ts">
70
+ <file name="index.ts" path="/home/rinor/explore/nest-mcp/src/decorators/index.ts">
85
71
  <metrics statements="2" coveredstatements="2" conditionals="0" coveredconditionals="0" methods="0" coveredmethods="0"/>
86
72
  <line num="1" count="1" type="stmt"/>
87
73
  <line num="2" count="1" type="stmt"/>
88
74
  </file>
89
- <file name="tool.decorator.ts" path="/home/rinor/explore/MCP-Nest/src/decorators/tool.decorator.ts">
75
+ <file name="tool.decorator.ts" path="/home/rinor/explore/nest-mcp/src/decorators/tool.decorator.ts">
90
76
  <metrics statements="4" coveredstatements="4" conditionals="0" coveredconditionals="0" methods="1" coveredmethods="1"/>
91
77
  <line num="1" count="1" type="stmt"/>
92
78
  <line num="2" count="1" type="stmt"/>
@@ -96,79 +82,107 @@
96
82
  </package>
97
83
  <package name="src.interfaces">
98
84
  <metrics statements="1" coveredstatements="1" conditionals="0" coveredconditionals="0" methods="0" coveredmethods="0"/>
99
- <file name="index.ts" path="/home/rinor/explore/MCP-Nest/src/interfaces/index.ts">
85
+ <file name="index.ts" path="/home/rinor/explore/nest-mcp/src/interfaces/index.ts">
100
86
  <metrics statements="1" coveredstatements="1" conditionals="0" coveredconditionals="0" methods="0" coveredmethods="0"/>
101
87
  <line num="1" count="1" type="stmt"/>
102
88
  </file>
103
89
  </package>
104
90
  <package name="src.services">
105
- <metrics statements="64" coveredstatements="50" conditionals="20" coveredconditionals="13" methods="19" coveredmethods="14"/>
106
- <file name="mcp-tools.discovery.ts" path="/home/rinor/explore/MCP-Nest/src/services/mcp-tools.discovery.ts">
107
- <metrics statements="64" coveredstatements="50" conditionals="20" coveredconditionals="13" methods="19" coveredmethods="14"/>
91
+ <metrics statements="92" coveredstatements="23" conditionals="28" coveredconditionals="1" methods="19" coveredmethods="2"/>
92
+ <file name="mcp-tools.discovery.ts" path="/home/rinor/explore/nest-mcp/src/services/mcp-tools.discovery.ts">
93
+ <metrics statements="92" coveredstatements="23" conditionals="28" coveredconditionals="1" methods="19" coveredmethods="2"/>
108
94
  <line num="2" count="1" type="stmt"/>
109
- <line num="3" count="1" type="stmt"/>
110
- <line num="4" count="1" type="stmt"/>
111
- <line num="5" count="1" type="stmt"/>
112
- <line num="6" count="1" type="stmt"/>
113
- <line num="7" count="1" type="stmt"/>
114
- <line num="31" count="1" type="stmt"/>
115
- <line num="42" count="1" type="stmt"/>
116
- <line num="51" count="1" type="stmt"/>
117
- <line num="60" count="0" type="stmt"/>
118
- <line num="61" count="0" type="stmt"/>
95
+ <line num="8" count="1" type="stmt"/>
96
+ <line num="9" count="1" type="stmt"/>
97
+ <line num="10" count="1" type="stmt"/>
98
+ <line num="11" count="1" type="stmt"/>
99
+ <line num="12" count="1" type="stmt"/>
100
+ <line num="49" count="1" type="stmt"/>
101
+ <line num="57" count="1" type="stmt"/>
119
102
  <line num="66" count="1" type="stmt"/>
120
- <line num="67" count="1" type="stmt"/>
121
- <line num="74" count="1" type="stmt"/>
122
- <line num="75" count="1" type="stmt"/>
123
- <line num="79" count="1" type="stmt"/>
103
+ <line num="77" count="1" type="stmt"/>
124
104
  <line num="83" count="1" type="stmt"/>
125
- <line num="84" count="1" type="stmt"/>
126
- <line num="85" count="1" type="stmt"/>
127
- <line num="86" count="29" type="stmt"/>
128
- <line num="87" count="27" type="stmt"/>
129
105
  <line num="89" count="1" type="stmt"/>
130
- <line num="90" count="27" type="cond" truecount="2" falsecount="1"/>
131
- <line num="91" count="0" type="stmt"/>
132
- <line num="93" count="27" type="stmt"/>
133
- <line num="94" count="211" type="stmt"/>
134
- <line num="95" count="211" type="stmt"/>
135
- <line num="97" count="211" type="cond" truecount="1" falsecount="0"/>
136
- <line num="98" count="210" type="stmt"/>
137
- <line num="101" count="1" type="stmt"/>
138
- <line num="103" count="1" type="stmt"/>
139
- <line num="114" count="2" type="stmt"/>
140
- <line num="115" count="2" type="stmt"/>
141
- <line num="122" count="2" type="stmt"/>
142
- <line num="128" count="2" type="stmt"/>
143
- <line num="129" count="1" type="stmt"/>
144
- <line num="131" count="1" type="cond" truecount="0" falsecount="1"/>
145
- <line num="132" count="0" type="stmt"/>
146
- <line num="138" count="1" type="stmt"/>
147
- <line num="139" count="1" type="stmt"/>
148
- <line num="141" count="1" type="cond" truecount="3" falsecount="0"/>
149
- <line num="142" count="1" type="stmt"/>
150
- <line num="143" count="1" type="cond" truecount="0" falsecount="1"/>
151
- <line num="144" count="0" type="stmt"/>
152
- <line num="149" count="1" type="stmt"/>
153
- <line num="152" count="1" type="stmt"/>
154
- <line num="154" count="1" type="stmt"/>
155
- <line num="155" count="1" type="stmt"/>
156
- <line num="156" count="1" type="stmt"/>
157
- <line num="163" count="1" type="cond" truecount="1" falsecount="1"/>
106
+ <line num="98" count="1" type="stmt"/>
107
+ <line num="105" count="1" type="stmt"/>
108
+ <line num="128" count="0" type="stmt"/>
109
+ <line num="129" count="0" type="stmt"/>
110
+ <line num="135" count="1" type="stmt"/>
111
+ <line num="136" count="1" type="stmt"/>
112
+ <line num="141" count="1" type="stmt"/>
113
+ <line num="144" count="4" type="stmt"/>
114
+ <line num="145" count="4" type="stmt"/>
115
+ <line num="146" count="4" type="stmt"/>
116
+ <line num="150" count="0" type="cond" truecount="0" falsecount="1"/>
117
+ <line num="151" count="0" type="stmt"/>
118
+ <line num="152" count="0" type="stmt"/>
119
+ <line num="153" count="0" type="stmt"/>
120
+ <line num="154" count="0" type="cond" truecount="0" falsecount="2"/>
121
+ <line num="159" count="0" type="stmt"/>
122
+ <line num="160" count="0" type="stmt"/>
123
+ <line num="161" count="0" type="stmt"/>
124
+ <line num="162" count="0" type="stmt"/>
125
+ <line num="163" count="0" type="cond" truecount="0" falsecount="3"/>
158
126
  <line num="164" count="0" type="stmt"/>
159
- <line num="167" count="1" type="cond" truecount="4" falsecount="1"/>
127
+ <line num="166" count="0" type="stmt"/>
128
+ <line num="167" count="0" type="cond" truecount="0" falsecount="3"/>
160
129
  <line num="168" count="0" type="stmt"/>
161
- <line num="172" count="1" type="stmt"/>
162
- <line num="175" count="0" type="cond" truecount="0" falsecount="1"/>
163
- <line num="176" count="0" type="stmt"/>
164
- <line num="181" count="0" type="stmt"/>
165
- <line num="190" count="1" type="stmt"/>
166
- <line num="192" count="5" type="cond" truecount="1" falsecount="0"/>
167
- <line num="193" count="5" type="stmt"/>
168
- <line num="204" count="0" type="stmt"/>
169
- <line num="210" count="0" type="stmt"/>
170
- <line num="216" count="0" type="stmt"/>
171
- <line num="222" count="0" type="stmt"/>
130
+ <line num="169" count="0" type="cond" truecount="0" falsecount="1"/>
131
+ <line num="170" count="0" type="stmt"/>
132
+ <line num="171" count="0" type="cond" truecount="0" falsecount="1"/>
133
+ <line num="172" count="0" type="stmt"/>
134
+ <line num="173" count="0" type="stmt"/>
135
+ <line num="174" count="0" type="cond" truecount="0" falsecount="1"/>
136
+ <line num="175" count="0" type="stmt"/>
137
+ <line num="179" count="0" type="stmt"/>
138
+ <line num="183" count="2" type="cond" truecount="1" falsecount="0"/>
139
+ <line num="184" count="2" type="stmt"/>
140
+ <line num="185" count="2" type="stmt"/>
141
+ <line num="187" count="0" type="stmt"/>
142
+ <line num="190" count="0" type="stmt"/>
143
+ <line num="192" count="0" type="stmt"/>
144
+ <line num="199" count="0" type="stmt"/>
145
+ <line num="203" count="0" type="stmt"/>
146
+ <line num="206" count="0" type="stmt"/>
147
+ <line num="207" count="0" type="stmt"/>
148
+ <line num="210" count="0" type="cond" truecount="0" falsecount="1"/>
149
+ <line num="211" count="0" type="stmt"/>
150
+ <line num="218" count="0" type="stmt"/>
151
+ <line num="219" count="0" type="stmt"/>
152
+ <line num="220" count="0" type="cond" truecount="0" falsecount="3"/>
153
+ <line num="221" count="0" type="stmt"/>
154
+ <line num="222" count="0" type="cond" truecount="0" falsecount="1"/>
155
+ <line num="223" count="0" type="stmt"/>
156
+ <line num="228" count="0" type="stmt"/>
157
+ <line num="231" count="0" type="stmt"/>
158
+ <line num="235" count="0" type="stmt"/>
159
+ <line num="236" count="0" type="stmt"/>
160
+ <line num="237" count="0" type="stmt"/>
161
+ <line num="244" count="0" type="cond" truecount="0" falsecount="2"/>
162
+ <line num="246" count="0" type="stmt"/>
163
+ <line num="249" count="0" type="stmt"/>
164
+ <line num="250" count="0" type="cond" truecount="0" falsecount="1"/>
165
+ <line num="251" count="0" type="stmt"/>
166
+ <line num="252" count="0" type="stmt"/>
167
+ <line num="253" count="0" type="stmt"/>
168
+ <line num="255" count="0" type="stmt"/>
169
+ <line num="259" count="0" type="stmt"/>
170
+ <line num="260" count="0" type="stmt"/>
171
+ <line num="261" count="0" type="stmt"/>
172
+ <line num="263" count="0" type="cond" truecount="0" falsecount="4"/>
173
+ <line num="264" count="0" type="stmt"/>
174
+ <line num="270" count="0" type="stmt"/>
175
+ <line num="279" count="0" type="stmt"/>
176
+ <line num="289" count="0" type="stmt"/>
177
+ <line num="290" count="0" type="stmt"/>
178
+ <line num="293" count="0" type="cond" truecount="0" falsecount="1"/>
179
+ <line num="294" count="0" type="stmt"/>
180
+ <line num="295" count="0" type="stmt"/>
181
+ <line num="300" count="0" type="stmt"/>
182
+ <line num="304" count="0" type="stmt"/>
183
+ <line num="305" count="0" type="stmt"/>
184
+ <line num="306" count="0" type="stmt"/>
185
+ <line num="307" count="0" type="stmt"/>
172
186
  </file>
173
187
  </package>
174
188
  </project>